Update Files

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

0
Deployment/.keepme Normal file
View File

11
Deployment/g1.frag Normal file
View File

@ -0,0 +1,11 @@
#version 110
uniform sampler2D texy;
varying vec2 texCoord;
void main()
{
gl_FragData[0] = texture2D(texy, texCoord);
}

12
Deployment/g1.vert Normal file
View File

@ -0,0 +1,12 @@
#version 110
attribute vec3 pos;
varying vec2 texCoord;
attribute vec2 tex;
void main()
{
gl_Position = vec4(pos.x, pos.y, 0.5, 1.0);
texCoord = tex;
}

84
Kinc/.clang-format Normal file
View File

@ -0,0 +1,84 @@
BasedOnStyle: LLVM
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlinesLeft: false
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: false
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
BeforeCatch: false
BeforeElse: true
IndentBraces: false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
ColumnLimit: 160
CommentPragmas: '^ IWYU pragma:'
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DeriveLineEnding: false
DerivePointerAlignment: false
DisableFormat: false
FixNamespaceComments: false
IndentCaseLabels: false
IndentWidth: 4
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: All
ObjCBlockIndentWidth: 4
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
ReflowComments: true
SortIncludes: true
SpaceAfterCStyleCast: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp03
TabWidth: 4
UseCRLF: false
UseTab: ForIndentation
---
Language: Cpp
---
Language: ObjC

2
Kinc/.clangd Normal file
View File

@ -0,0 +1,2 @@
CompileFlags:
Add: [-D,KINC_EDITOR_SUPPORT, -Wall]

View File

@ -0,0 +1,147 @@
#include <kinc/audio2/audio.h>
#include <kinc/system.h>
#include <kinc/backend/SystemMicrosoft.h>
#include <kinc/backend/Windows.h>
#include <dsound.h>
namespace {
IDirectSound8 *dsound = nullptr;
IDirectSoundBuffer *dbuffer = nullptr;
const DWORD dsize = 50 * 1024;
const int samplesPerSecond = 44100;
const int bitsPerSample = 16;
DWORD lastPlayPosition = 0;
bool secondHalfFilled = false;
const int gap = 10 * 1024;
DWORD writePos = gap;
void (*a2_callback)(kinc_a2_buffer_t *buffer, int samples) = nullptr;
kinc_a2_buffer_t a2_buffer;
}
static bool initialized = false;
void kinc_a2_init() {
if (initialized) {
return;
}
initialized = true;
a2_buffer.read_location = 0;
a2_buffer.write_location = 0;
a2_buffer.data_size = 128 * 1024;
a2_buffer.data = new uint8_t[a2_buffer.data_size];
kinc_microsoft_affirm(DirectSoundCreate8(nullptr, &dsound, nullptr));
// TODO (DK) only for the main window?
kinc_microsoft_affirm(dsound->SetCooperativeLevel(kinc_windows_window_handle(0), DSSCL_PRIORITY));
WAVEFORMATEX waveFormat;
waveFormat.wFormatTag = WAVE_FORMAT_PCM;
waveFormat.nSamplesPerSec = samplesPerSecond;
waveFormat.wBitsPerSample = bitsPerSample;
waveFormat.nChannels = 2;
waveFormat.nBlockAlign = (waveFormat.wBitsPerSample / 8) * waveFormat.nChannels;
waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign;
waveFormat.cbSize = 0;
DSBUFFERDESC bufferDesc;
bufferDesc.dwSize = sizeof(DSBUFFERDESC);
bufferDesc.dwFlags = DSBCAPS_GLOBALFOCUS;
bufferDesc.dwBufferBytes = dsize;
bufferDesc.dwReserved = 0;
bufferDesc.lpwfxFormat = &waveFormat;
bufferDesc.guid3DAlgorithm = GUID_NULL;
kinc_microsoft_affirm(dsound->CreateSoundBuffer(&bufferDesc, &dbuffer, nullptr));
DWORD size1;
uint8_t *buffer1;
kinc_microsoft_affirm(dbuffer->Lock(writePos, gap, (void **)&buffer1, &size1, nullptr, nullptr, 0));
for (int i = 0; i < gap; ++i)
buffer1[i] = 0;
kinc_microsoft_affirm(dbuffer->Unlock(buffer1, size1, nullptr, 0));
kinc_microsoft_affirm(dbuffer->Play(0, 0, DSBPLAY_LOOPING));
}
void kinc_a2_set_callback(void (*kinc_a2_audio_callback)(kinc_a2_buffer_t *buffer, int samples)) {
a2_callback = kinc_a2_audio_callback;
}
namespace {
void copySample(uint8_t *buffer, DWORD &index) {
float value = *(float *)&a2_buffer.data[a2_buffer.read_location];
a2_buffer.read_location += 4;
if (a2_buffer.read_location >= a2_buffer.data_size) {
a2_buffer.read_location = 0;
}
*(int16_t *)&buffer[index] = static_cast<int16_t>(value * 32767);
index += 2;
}
}
void kinc_a2_update() {
DWORD playPosition;
DWORD writePosition;
kinc_microsoft_affirm(dbuffer->GetCurrentPosition(&playPosition, &writePosition));
int dif;
if (writePos >= writePosition)
dif = writePos - writePosition;
else
dif = dsize - writePosition + writePos;
if (dif < gap)
return;
if (writePos + gap >= dsize) {
if (playPosition >= writePos || playPosition <= gap)
return;
if (writePosition >= writePos || writePosition <= gap)
return;
}
else {
if (playPosition >= writePos && playPosition <= writePos + gap)
return;
if (writePosition >= writePos && writePosition <= writePos + gap)
return;
}
a2_callback(&a2_buffer, gap / 2);
DWORD size1, size2;
uint8_t *buffer1, *buffer2;
kinc_microsoft_affirm(dbuffer->Lock(writePos, gap, (void **)&buffer1, &size1, (void **)&buffer2, &size2, 0));
for (DWORD i = 0; i < size1 - (bitsPerSample / 8 - 1);) {
copySample(buffer1, i);
}
writePos += size1;
if (buffer2 != nullptr) {
for (DWORD i = 0; i < size2 - (bitsPerSample / 8 - 1);) {
copySample(buffer2, i);
}
writePos = size2;
}
kinc_microsoft_affirm(dbuffer->Unlock(buffer1, size1, buffer2, size2));
if (writePos >= dsize)
writePos -= dsize;
}
void kinc_a2_shutdown() {
if (dbuffer != nullptr) {
dbuffer->Release();
dbuffer = nullptr;
}
if (dsound != nullptr) {
dsound->Release();
dsound = nullptr;
}
}

View File

@ -0,0 +1,296 @@
#include <kinc/audio2/audio.h>
#include <kinc/backend/SystemMicrosoft.h>
#include <kinc/error.h>
#include <kinc/log.h>
// Windows 7
#define WINVER 0x0601
#define _WIN32_WINNT 0x0601
#define NOATOM
#define NOCLIPBOARD
#define NOCOLOR
#define NOCOMM
#define NOCTLMGR
#define NODEFERWINDOWPOS
#define NODRAWTEXT
//#define NOGDI
#define NOGDICAPMASKS
#define NOHELP
#define NOICONS
#define NOKANJI
#define NOKEYSTATES
#define NOMB
#define NOMCX
#define NOMEMMGR
#define NOMENUS
#define NOMETAFILE
#define NOMINMAX
//#define NOMSG
#define NONLS
#define NOOPENFILE
#define NOPROFILER
#define NORASTEROPS
#define NOSCROLL
#define NOSERVICE
#define NOSHOWWINDOW
#define NOSOUND
#define NOSYSCOMMANDS
#define NOSYSMETRICS
#define NOTEXTMETRIC
//#define NOUSER
#define NOVIRTUALKEYCODES
#define NOWH
#define NOWINMESSAGES
#define NOWINOFFSETS
#define NOWINSTYLES
#define WIN32_LEAN_AND_MEAN
#include <initguid.h>
#include <AudioClient.h>
#include <mmdeviceapi.h>
// MIDL_INTERFACE("1CB9AD4C-DBFA-4c32-B178-C2F568A703B2")
DEFINE_GUID(IID_IAudioClient, 0x1CB9AD4C, 0xDBFA, 0x4c32, 0xB1, 0x78, 0xC2, 0xF5, 0x68, 0xA7, 0x03, 0xB2);
// MIDL_INTERFACE("F294ACFC-3146-4483-A7BF-ADDCA7C260E2")
DEFINE_GUID(IID_IAudioRenderClient, 0xF294ACFC, 0x3146, 0x4483, 0xA7, 0xBF, 0xAD, 0xDC, 0xA7, 0xC2, 0x60, 0xE2);
// MIDL_INTERFACE("A95664D2-9614-4F35-A746-DE8DB63617E6")
DEFINE_GUID(IID_IMMDeviceEnumerator, 0xA95664D2, 0x9614, 0x4F35, 0xA7, 0x46, 0xDE, 0x8D, 0xB6, 0x36, 0x17, 0xE6);
// DECLSPEC_UUID("BCDE0395-E52F-467C-8E3D-C4579291692E")
DEFINE_GUID(CLSID_MMDeviceEnumerator, 0xBCDE0395, 0xE52F, 0x467C, 0x8E, 0x3D, 0xC4, 0x57, 0x92, 0x91, 0x69, 0x2E);
// based on the implementation in soloud and Microsoft sample code
static volatile void (*a2_callback)(kinc_a2_buffer_t *buffer, int samples) = NULL;
static kinc_a2_buffer_t a2_buffer;
static IMMDeviceEnumerator *deviceEnumerator;
static IMMDevice *device;
static IAudioClient *audioClient = NULL;
static IAudioRenderClient *renderClient = NULL;
static HANDLE bufferEndEvent = 0;
static HANDLE audioProcessingDoneEvent;
static UINT32 bufferFrames;
static WAVEFORMATEX requestedFormat;
static WAVEFORMATEX *closestFormat;
static WAVEFORMATEX *format;
static bool initDefaultDevice() {
if (renderClient != NULL) {
renderClient->lpVtbl->Release(renderClient);
renderClient = NULL;
}
if (audioClient != NULL) {
audioClient->lpVtbl->Release(audioClient);
audioClient = NULL;
}
if (bufferEndEvent != 0) {
CloseHandle(bufferEndEvent);
bufferEndEvent = 0;
}
kinc_log(KINC_LOG_LEVEL_INFO, "Initializing a new default audio device.");
HRESULT hr = deviceEnumerator->lpVtbl->GetDefaultAudioEndpoint(deviceEnumerator, eRender, eConsole, &device);
if (hr == S_OK) {
hr = device->lpVtbl->Activate(device, &IID_IAudioClient, CLSCTX_ALL, 0, (void **)&audioClient);
}
if (hr == S_OK) {
const int sampleRate = 48000;
format = &requestedFormat;
memset(&requestedFormat, 0, sizeof(WAVEFORMATEX));
requestedFormat.nChannels = 2;
requestedFormat.nSamplesPerSec = sampleRate;
requestedFormat.wFormatTag = WAVE_FORMAT_PCM;
requestedFormat.wBitsPerSample = sizeof(short) * 8;
requestedFormat.nBlockAlign = (requestedFormat.nChannels * requestedFormat.wBitsPerSample) / 8;
requestedFormat.nAvgBytesPerSec = requestedFormat.nSamplesPerSec * requestedFormat.nBlockAlign;
requestedFormat.cbSize = 0;
HRESULT supported = audioClient->lpVtbl->IsFormatSupported(audioClient, AUDCLNT_SHAREMODE_SHARED, format, &closestFormat);
if (supported == S_FALSE) {
kinc_log(KINC_LOG_LEVEL_WARNING, "Falling back to the system's preferred WASAPI mix format.", supported);
if (closestFormat != NULL) {
format = closestFormat;
}
else {
audioClient->lpVtbl->GetMixFormat(audioClient, &format);
}
}
HRESULT result =
audioClient->lpVtbl->Initialize(audioClient, AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, 40 * 1000 * 10, 0, format, 0);
if (result != S_OK) {
kinc_log(KINC_LOG_LEVEL_WARNING, "Could not initialize WASAPI audio, going silent (error code 0x%x).", result);
return false;
}
kinc_a2_samples_per_second = format->nSamplesPerSec;
a2_buffer.format.samples_per_second = kinc_a2_samples_per_second;
a2_buffer.format.bits_per_sample = 16;
a2_buffer.format.channels = 2;
bufferFrames = 0;
kinc_microsoft_affirm(audioClient->lpVtbl->GetBufferSize(audioClient, &bufferFrames));
kinc_microsoft_affirm(audioClient->lpVtbl->GetService(audioClient, &IID_IAudioRenderClient, (void **)&renderClient));
bufferEndEvent = CreateEvent(0, FALSE, FALSE, 0);
kinc_affirm(bufferEndEvent != 0);
kinc_microsoft_affirm(audioClient->lpVtbl->SetEventHandle(audioClient, bufferEndEvent));
return true;
}
else {
kinc_log(KINC_LOG_LEVEL_WARNING, "Could not initialize WASAPI audio.");
return false;
}
}
static void copyS16Sample(int16_t *buffer) {
float value = *(float *)&a2_buffer.data[a2_buffer.read_location];
a2_buffer.read_location += 4;
if (a2_buffer.read_location >= a2_buffer.data_size)
a2_buffer.read_location = 0;
*buffer = (int16_t)(value * 32767);
}
static void copyFloatSample(float *buffer) {
float value = *(float *)&a2_buffer.data[a2_buffer.read_location];
a2_buffer.read_location += 4;
if (a2_buffer.read_location >= a2_buffer.data_size)
a2_buffer.read_location = 0;
*buffer = value;
}
static void submitEmptyBuffer(unsigned frames) {
BYTE *buffer = NULL;
HRESULT result = renderClient->lpVtbl->GetBuffer(renderClient, frames, &buffer);
if (FAILED(result)) {
return;
}
memset(buffer, 0, frames * format->nBlockAlign);
result = renderClient->lpVtbl->ReleaseBuffer(renderClient, frames, 0);
}
static void submitBuffer(unsigned frames) {
BYTE *buffer = NULL;
HRESULT result = renderClient->lpVtbl->GetBuffer(renderClient, frames, &buffer);
if (FAILED(result)) {
if (result == AUDCLNT_E_DEVICE_INVALIDATED) {
initDefaultDevice();
submitEmptyBuffer(bufferFrames);
audioClient->lpVtbl->Start(audioClient);
}
return;
}
if (a2_callback != NULL) {
a2_callback(&a2_buffer, frames * 2);
memset(buffer, 0, frames * format->nBlockAlign);
if (format->wFormatTag == WAVE_FORMAT_PCM) {
for (UINT32 i = 0; i < frames; ++i) {
copyS16Sample((int16_t *)&buffer[i * format->nBlockAlign]);
copyS16Sample((int16_t *)&buffer[i * format->nBlockAlign + 2]);
}
}
else {
for (UINT32 i = 0; i < frames; ++i) {
copyFloatSample((float *)&buffer[i * format->nBlockAlign]);
copyFloatSample((float *)&buffer[i * format->nBlockAlign + 4]);
}
}
}
else {
memset(buffer, 0, frames * format->nBlockAlign);
}
result = renderClient->lpVtbl->ReleaseBuffer(renderClient, frames, 0);
if (FAILED(result)) {
if (result == AUDCLNT_E_DEVICE_INVALIDATED) {
initDefaultDevice();
submitEmptyBuffer(bufferFrames);
audioClient->lpVtbl->Start(audioClient);
}
}
}
static DWORD WINAPI audioThread(LPVOID ignored) {
submitBuffer(bufferFrames);
audioClient->lpVtbl->Start(audioClient);
while (WAIT_OBJECT_0 != WaitForSingleObject(audioProcessingDoneEvent, 0)) {
WaitForSingleObject(bufferEndEvent, INFINITE);
UINT32 padding = 0;
HRESULT result = audioClient->lpVtbl->GetCurrentPadding(audioClient, &padding);
if (FAILED(result)) {
if (result == AUDCLNT_E_DEVICE_INVALIDATED) {
initDefaultDevice();
submitEmptyBuffer(bufferFrames);
audioClient->lpVtbl->Start(audioClient);
}
continue;
}
UINT32 frames = bufferFrames - padding;
submitBuffer(frames);
}
return 0;
}
void kinc_windows_co_initialize(void);
static bool initialized = false;
void kinc_a2_init() {
if (initialized) {
return;
}
initialized = true;
a2_buffer.read_location = 0;
a2_buffer.write_location = 0;
a2_buffer.data_size = 128 * 1024;
a2_buffer.data = (uint8_t *)malloc(a2_buffer.data_size);
audioProcessingDoneEvent = CreateEvent(0, FALSE, FALSE, 0);
kinc_affirm(audioProcessingDoneEvent != 0);
kinc_windows_co_initialize();
kinc_microsoft_affirm(CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, &IID_IMMDeviceEnumerator, (void **)&deviceEnumerator));
if (initDefaultDevice()) {
CreateThread(0, 65536, audioThread, NULL, 0, 0);
}
}
void kinc_a2_set_callback(void (*kinc_a2_audio_callback)(kinc_a2_buffer_t *buffer, int samples)) {
a2_callback = kinc_a2_audio_callback;
}
void kinc_a2_update() {}
#define SAFE_RELEASE(punk) \
if ((punk) != NULL) { \
(punk)->Release(); \
(punk) = NULL; \
}
void kinc_a2_shutdown() {
// Wait for last data in buffer to play before stopping.
// Sleep((DWORD)(hnsActualDuration/REFTIMES_PER_MILLISEC/2));
// affirm(pAudioClient->Stop()); // Stop playing.
// CoTaskMemFree(pwfx);
// SAFE_RELEASE(pEnumerator)
// SAFE_RELEASE(pDevice)
// SAFE_RELEASE(pAudioClient)
// SAFE_RELEASE(pRenderClient)
}

View File

@ -0,0 +1,301 @@
#include <kinc/audio2/audio.h>
#include <kinc/backend/SystemMicrosoft.h>
#include <kinc/error.h>
#include <kinc/log.h>
#include <kinc/threads/thread.h>
#include <AudioClient.h>
#include <Windows.h>
#include <initguid.h>
#ifdef KORE_WINRT
#include <mfapi.h>
#endif
#include <mmdeviceapi.h>
#include <wrl/implements.h>
using namespace Kore;
#ifdef KORE_WINRT
using namespace ::Microsoft::WRL;
using namespace Windows::Media::Devices;
using namespace Windows::Storage::Streams;
#endif
template <class T> void SafeRelease(__deref_inout_opt T **ppT) {
T *pTTemp = *ppT;
*ppT = nullptr;
if (pTTemp) {
pTTemp->Release();
}
}
#define SAFE_RELEASE(punk) \
if ((punk) != NULL) { \
(punk)->Release(); \
(punk) = NULL; \
}
// based on the implementation in soloud and Microsoft sample code
namespace {
kinc_thread_t thread;
void (*a2_callback)(kinc_a2_buffer_t *buffer, int samples) = nullptr;
kinc_a2_buffer_t a2_buffer;
IMMDeviceEnumerator *deviceEnumerator;
IMMDevice *device;
IAudioClient *audioClient = NULL;
IAudioRenderClient *renderClient = NULL;
HANDLE bufferEndEvent = 0;
HANDLE audioProcessingDoneEvent;
UINT32 bufferFrames;
WAVEFORMATEX requestedFormat;
WAVEFORMATEX *closestFormat;
WAVEFORMATEX *format;
bool initDefaultDevice();
void audioThread(LPVOID);
#ifdef KORE_WINRT
class AudioRenderer : public RuntimeClass<RuntimeClassFlags<ClassicCom>, FtmBase, IActivateAudioInterfaceCompletionHandler> {
public:
STDMETHOD(ActivateCompleted)(IActivateAudioInterfaceAsyncOperation *operation) {
IUnknown *audioInterface = nullptr;
HRESULT hrActivateResult = S_OK;
HRESULT hr = operation->GetActivateResult(&hrActivateResult, &audioInterface);
if (SUCCEEDED(hr) && SUCCEEDED(hrActivateResult)) {
audioInterface->QueryInterface(IID_PPV_ARGS(&audioClient));
initDefaultDevice();
audioThread(nullptr);
}
return S_OK;
}
};
ComPtr<AudioRenderer> renderer;
#endif
bool initDefaultDevice() {
#ifdef KORE_WINRT
HRESULT hr = S_OK;
#else
if (renderClient != NULL) {
renderClient->Release();
renderClient = NULL;
}
if (audioClient != NULL) {
audioClient->Release();
audioClient = NULL;
}
if (bufferEndEvent != 0) {
CloseHandle(bufferEndEvent);
bufferEndEvent = 0;
}
kinc_log(KINC_LOG_LEVEL_INFO, "Initializing a new default audio device.");
HRESULT hr = deviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &device);
if (hr == S_OK) {
hr = device->Activate(__uuidof(IAudioClient), CLSCTX_ALL, 0, reinterpret_cast<void **>(&audioClient));
}
#endif
if (hr == S_OK) {
const int sampleRate = 48000;
format = &requestedFormat;
memset(&requestedFormat, 0, sizeof(WAVEFORMATEX));
requestedFormat.nChannels = 2;
requestedFormat.nSamplesPerSec = sampleRate;
requestedFormat.wFormatTag = WAVE_FORMAT_PCM;
requestedFormat.wBitsPerSample = sizeof(short) * 8;
requestedFormat.nBlockAlign = (requestedFormat.nChannels * requestedFormat.wBitsPerSample) / 8;
requestedFormat.nAvgBytesPerSec = requestedFormat.nSamplesPerSec * requestedFormat.nBlockAlign;
requestedFormat.cbSize = 0;
HRESULT supported = audioClient->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, format, &closestFormat);
if (supported == S_FALSE) {
kinc_log(KINC_LOG_LEVEL_WARNING, "Falling back to the system's preferred WASAPI mix format.", supported);
if (closestFormat != nullptr) {
format = closestFormat;
}
else {
audioClient->GetMixFormat(&format);
}
}
HRESULT result = audioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, 40 * 1000 * 10, 0, format, 0);
if (result != S_OK) {
kinc_log(KINC_LOG_LEVEL_WARNING, "Could not initialize WASAPI audio, going silent (error code 0x%x).", result);
return false;
}
kinc_a2_samples_per_second = format->nSamplesPerSec;
a2_buffer.format.samples_per_second = kinc_a2_samples_per_second;
bufferFrames = 0;
kinc_microsoft_affirm(audioClient->GetBufferSize(&bufferFrames));
kinc_microsoft_affirm(audioClient->GetService(__uuidof(IAudioRenderClient), reinterpret_cast<void **>(&renderClient)));
bufferEndEvent = CreateEvent(0, FALSE, FALSE, 0);
kinc_affirm(bufferEndEvent != 0);
kinc_microsoft_affirm(audioClient->SetEventHandle(bufferEndEvent));
return true;
}
else {
kinc_log(KINC_LOG_LEVEL_WARNING, "Could not initialize WASAPI audio.");
return false;
}
}
void copyS16Sample(s16 *buffer) {
float value = *(float *)&a2_buffer.data[a2_buffer.read_location];
a2_buffer.read_location += 4;
if (a2_buffer.read_location >= a2_buffer.data_size) a2_buffer.read_location = 0;
*buffer = (s16)(value * 32767);
}
void copyFloatSample(float *buffer) {
float value = *(float *)&a2_buffer.data[a2_buffer.read_location];
a2_buffer.read_location += 4;
if (a2_buffer.read_location >= a2_buffer.data_size) a2_buffer.read_location = 0;
*buffer = value;
}
void submitEmptyBuffer(unsigned frames) {
BYTE *buffer = nullptr;
HRESULT result = renderClient->GetBuffer(frames, &buffer);
if (FAILED(result)) {
return;
}
memset(buffer, 0, frames * format->nBlockAlign);
result = renderClient->ReleaseBuffer(frames, 0);
}
void submitBuffer(unsigned frames) {
BYTE *buffer = nullptr;
HRESULT result = renderClient->GetBuffer(frames, &buffer);
if (FAILED(result)) {
if (result == AUDCLNT_E_DEVICE_INVALIDATED) {
initDefaultDevice();
submitEmptyBuffer(bufferFrames);
audioClient->Start();
}
return;
}
if (a2_callback != nullptr) {
a2_callback(&a2_buffer, frames * 2);
memset(buffer, 0, frames * format->nBlockAlign);
if (format->wFormatTag == WAVE_FORMAT_PCM) {
for (UINT32 i = 0; i < frames; ++i) {
copyS16Sample((s16 *)&buffer[i * format->nBlockAlign]);
copyS16Sample((s16 *)&buffer[i * format->nBlockAlign + 2]);
}
}
else {
for (UINT32 i = 0; i < frames; ++i) {
copyFloatSample((float *)&buffer[i * format->nBlockAlign]);
copyFloatSample((float *)&buffer[i * format->nBlockAlign + 4]);
}
}
}
else {
memset(buffer, 0, frames * format->nBlockAlign);
}
result = renderClient->ReleaseBuffer(frames, 0);
if (FAILED(result)) {
if (result == AUDCLNT_E_DEVICE_INVALIDATED) {
initDefaultDevice();
submitEmptyBuffer(bufferFrames);
audioClient->Start();
}
}
}
void audioThread(LPVOID) {
submitBuffer(bufferFrames);
audioClient->Start();
while (WAIT_OBJECT_0 != WaitForSingleObject(audioProcessingDoneEvent, 0)) {
WaitForSingleObject(bufferEndEvent, INFINITE);
UINT32 padding = 0;
HRESULT result = audioClient->GetCurrentPadding(&padding);
if (FAILED(result)) {
if (result == AUDCLNT_E_DEVICE_INVALIDATED) {
initDefaultDevice();
submitEmptyBuffer(bufferFrames);
audioClient->Start();
}
continue;
}
UINT32 frames = bufferFrames - padding;
submitBuffer(frames);
}
}
} // namespace
#ifndef KORE_WINRT
extern "C" void kinc_windows_co_initialize(void);
#endif
static bool initialized = false;
void kinc_a2_init() {
if (initialized) {
return;
}
initialized = true;
a2_buffer.read_location = 0;
a2_buffer.write_location = 0;
a2_buffer.data_size = 128 * 1024;
a2_buffer.data = (uint8_t *)malloc(a2_buffer.data_size);
audioProcessingDoneEvent = CreateEvent(0, FALSE, FALSE, 0);
kinc_affirm(audioProcessingDoneEvent != 0);
#ifdef KORE_WINRT
renderer = Make<AudioRenderer>();
IActivateAudioInterfaceAsyncOperation *asyncOp;
Platform::String ^ deviceId = MediaDevice::GetDefaultAudioRenderId(Windows::Media::Devices::AudioDeviceRole::Default);
kinc_microsoft_affirm(ActivateAudioInterfaceAsync(deviceId->Data(), __uuidof(IAudioClient2), nullptr, renderer.Get(), &asyncOp));
SafeRelease(&asyncOp);
#else
kinc_windows_co_initialize();
kinc_microsoft_affirm(
CoCreateInstance(__uuidof(MMDeviceEnumerator), 0, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), reinterpret_cast<void **>(&deviceEnumerator)));
if (initDefaultDevice()) {
kinc_thread_init(&thread, audioThread, NULL);
}
#endif
}
void kinc_a2_set_callback(void (*kinc_a2_audio_callback)(kinc_a2_buffer_t *buffer, int samples)) {
a2_callback = kinc_a2_audio_callback;
}
void kinc_a2_update() {}
void kinc_a2_shutdown() {
// Wait for last data in buffer to play before stopping.
// Sleep((DWORD)(hnsActualDuration/REFTIMES_PER_MILLISEC/2));
// affirm(pAudioClient->Stop()); // Stop playing.
// CoTaskMemFree(pwfx);
// SAFE_RELEASE(pEnumerator)
// SAFE_RELEASE(pDevice)
// SAFE_RELEASE(pAudioClient)
// SAFE_RELEASE(pRenderClient)
}

View File

@ -0,0 +1,62 @@
#include <Kore/Audio2/Audio.h>
#include <Kore/Audio3/Audio.h>
using namespace Kore;
namespace {
const int channelCount = 64;
Audio3::Channel channels[channelCount];
void callback(int samples) {
for (int i = 0; i < channelCount; ++i) {
channels[i].callback(samples);
}
for (int i = 0; i < samples; ++i) {
float value = 0;
for (int i = 0; i < channelCount; ++i) {
value += *(float *)&channels[i].buffer.data[Audio2::buffer.readLocation];
channels[i].buffer.readLocation += 4;
if (channels[i].buffer.readLocation >= channels[i].buffer.dataSize)
channels[i].buffer.readLocation = 0;
}
*(float *)&Audio2::buffer.data[Audio2::buffer.writeLocation] = value;
Audio2::buffer.writeLocation += 4;
if (Audio2::buffer.writeLocation >= Audio2::buffer.dataSize)
Audio2::buffer.writeLocation = 0;
}
}
}
void Audio3::init() {
for (int i = 0; i < channelCount; ++i) {
channels[i].active = false;
channels[i].buffer.readLocation = 0;
channels[i].buffer.writeLocation = 0;
channels[i].buffer.dataSize = 128 * 1024;
channels[i].buffer.data = new u8[channels[i].buffer.dataSize];
}
Audio2::init();
Audio2::audioCallback = callback;
}
void Audio3::update() {
Audio2::update();
}
void Audio3::shutdown() {
Audio2::shutdown();
}
Audio3::Channel *Audio3::createChannel(vec3 origin, AudioCallback callback) {
for (int i = 0; i < channelCount; ++i) {
if (!channels[i].active) {
return &channels[i];
}
}
return nullptr;
}
void Audio3::destroyChannel(Channel *channel) {
channel->active = false;
}

View File

@ -0,0 +1,43 @@
#ifdef KORE_WINDOWSAPP
#include <Kore/Audio3/TextToSpeech.h>
#include <Kore/Log.h>
#include <ppltasks.h>
using namespace Kore;
using namespace Windows::Media::SpeechSynthesis;
using namespace Windows::Media::Core;
using namespace Windows::Media::Playback;
SpeechSynthesizer ^ speechSynthesizer;
MediaPlayer ^ mediaPlayer;
void TextToSpeech::init() {
speechSynthesizer = ref new SpeechSynthesizer();
// auto voices = speechSynthesizer->AllVoices;
// for (int i = 0; i < voices->Size; i++) {
// auto voiceInfo = voices->GetAt(i);
// OutputDebugStringW(voiceInfo->DisplayName->Data());
// OutputDebugStringW(voiceInfo->Description->Data());
//}
mediaPlayer = ref new MediaPlayer();
}
Platform::String ^
CharToString(const char *char_array) {
std::string s_str = std::string(char_array);
std::wstring wid_str = std::wstring(s_str.begin(), s_str.end());
const wchar_t *w_char = wid_str.c_str();
return ref new Platform::String(w_char);
}
void TextToSpeech::speakText(const char *text) {
concurrency::create_task(speechSynthesizer->SynthesizeTextToStreamAsync(CharToString(text))).then([](SpeechSynthesisStream ^ stream) {
mediaPlayer->Source = MediaSource::CreateFromStream(stream, stream->ContentType);
// mediaPlayer->Volume = 1;
mediaPlayer->Play();
// mediaPlayer->
});
}
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,147 @@
#include "ComputeImpl.h"
#include "ogl.h"
#include <Kore/Compute/Compute.h>
#include <Kore/Graphics3/Graphics.h>
#include <Kore/Math/Core.h>
#include <stdio.h>
using namespace Kore;
#if defined(KORE_WINDOWS) || (defined(KORE_LINUX) && defined(GL_VERSION_4_3)) || (defined(KORE_ANDROID) && defined(GL_ES_VERSION_3_1))
#define HAS_COMPUTE
#endif
ComputeShaderImpl::ComputeShaderImpl(void *source, int length) : _length(length) {
_source = new char[length + 1];
for (int i = 0; i < length; ++i) {
_source[i] = ((char *)source)[i];
}
_source[length] = 0;
#ifdef HAS_COMPUTE
_id = glCreateShader(GL_COMPUTE_SHADER);
glCheckErrors();
glShaderSource(_id, 1, &_source, nullptr);
glCompileShader(_id);
int result;
glGetShaderiv(_id, GL_COMPILE_STATUS, &result);
if (result != GL_TRUE) {
int length;
glGetShaderiv(_id, GL_INFO_LOG_LENGTH, &length);
char *errormessage = new char[length];
glGetShaderInfoLog(_id, length, nullptr, errormessage);
log(Error, "GLSL compiler error: %s\n", errormessage);
delete[] errormessage;
}
_programid = glCreateProgram();
glAttachShader(_programid, _id);
glLinkProgram(_programid);
glGetProgramiv(_programid, GL_LINK_STATUS, &result);
if (result != GL_TRUE) {
int length;
glGetProgramiv(_programid, GL_INFO_LOG_LENGTH, &length);
char *errormessage = new char[length];
glGetProgramInfoLog(_programid, length, nullptr, errormessage);
log(Error, "GLSL linker error: %s\n", errormessage);
delete[] errormessage;
}
#endif
}
ComputeShaderImpl::~ComputeShaderImpl() {
delete[] _source;
_source = nullptr;
#ifdef HAS_COMPUTE
glDeleteProgram(_programid);
glDeleteShader(_id);
#endif
}
ComputeShader::ComputeShader(void *_data, int length) : ComputeShaderImpl(_data, length) {}
ComputeConstantLocation ComputeShader::getConstantLocation(const char *name) {
ComputeConstantLocation location;
#ifdef HAS_COMPUTE
location.location = glGetUniformLocation(_programid, name);
glCheckErrors2();
if (location.location < 0) {
log(Warning, "Uniform %s not found.", name);
}
#endif
return location;
}
ComputeTextureUnit ComputeShader::getTextureUnit(const char *name) {
ComputeTextureUnit unit;
unit.unit = 0;
return unit;
}
void Compute::setFloat(ComputeConstantLocation location, float value) {
#ifdef HAS_COMPUTE
glUniform1f(location.location, value);
glCheckErrors2();
#endif
}
void Compute::setBuffer(ShaderStorageBuffer *buffer, int index) {
#ifdef HAS_COMPUTE
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, index, buffer->bufferId);
glCheckErrors2();
#endif
}
void Compute::setTexture(ComputeTextureUnit unit, Graphics4::Texture *texture, Access access) {
#ifdef HAS_COMPUTE
glActiveTexture(GL_TEXTURE0 + unit.unit);
glCheckErrors2();
GLenum glaccess = access == Access::Read ? GL_READ_ONLY : (access == Access::Write ? GL_WRITE_ONLY : GL_READ_WRITE);
glBindImageTexture(0, texture->texture, 0, GL_FALSE, 0, glaccess, GL_RGBA32F);
glCheckErrors2();
#endif
}
void Compute::setTexture(ComputeTextureUnit unit, Graphics4::RenderTarget *target, Access access) {}
void Compute::setSampledTexture(ComputeTextureUnit unit, Graphics4::Texture *texture) {}
void Compute::setSampledTexture(ComputeTextureUnit unit, Graphics4::RenderTarget *target) {}
void Compute::setSampledDepthTexture(ComputeTextureUnit unit, Graphics4::RenderTarget *target) {}
void Compute::setTextureAddressing(ComputeTextureUnit unit, Graphics4::TexDir dir, Graphics4::TextureAddressing addressing) {}
void Compute::setTexture3DAddressing(ComputeTextureUnit unit, Graphics4::TexDir dir, Graphics4::TextureAddressing addressing) {}
void Compute::setTextureMagnificationFilter(ComputeTextureUnit unit, Graphics4::TextureFilter filter) {}
void Compute::setTexture3DMagnificationFilter(ComputeTextureUnit unit, Graphics4::TextureFilter filter) {}
void Compute::setTextureMinificationFilter(ComputeTextureUnit unit, Graphics4::TextureFilter filter) {}
void Compute::setTexture3DMinificationFilter(ComputeTextureUnit unit, Graphics4::TextureFilter filter) {}
void Compute::setTextureMipmapFilter(ComputeTextureUnit unit, Graphics4::MipmapFilter filter) {}
void Compute::setTexture3DMipmapFilter(ComputeTextureUnit unit, Graphics4::MipmapFilter filter) {}
void Compute::setShader(ComputeShader *shader) {
#ifdef HAS_COMPUTE
glUseProgram(shader->_programid);
glCheckErrors2();
#endif
}
void Compute::compute(int x, int y, int z) {
#ifdef HAS_COMPUTE
glDispatchCompute(x, y, z);
glCheckErrors2();
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
glCheckErrors2();
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
glCheckErrors2();
#endif
}

View File

@ -0,0 +1,23 @@
#pragma once
namespace Kore {
class ComputeConstantLocationImpl {
public:
int location;
};
class ComputeTextureUnitImpl {
public:
int unit;
};
class ComputeShaderImpl {
public:
ComputeShaderImpl(void *source, int length);
virtual ~ComputeShaderImpl();
uint _id;
uint _programid;
char *_source;
int _length;
};
}

View File

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

View File

@ -0,0 +1,58 @@
#include "ogl.h"
#include <Kore/Graphics3/Graphics.h>
using namespace Kore;
Graphics3::IndexBuffer *IndexBufferImpl::current = nullptr;
IndexBufferImpl::IndexBufferImpl(int count) : myCount(count) {}
Graphics3::IndexBuffer::IndexBuffer(int indexCount) : IndexBufferImpl(indexCount) {
glGenBuffers(1, &bufferId);
glCheckErrors();
data = new int[indexCount];
#if defined(KORE_ANDROID) || defined(KORE_PI)
shortData = new u16[indexCount];
#endif
}
Graphics3::IndexBuffer::~IndexBuffer() {
unset();
delete[] data;
}
int *Graphics3::IndexBuffer::lock() {
return data;
}
void Graphics3::IndexBuffer::unlock() {
#if defined(KORE_ANDROID) || defined(KORE_PI)
for (int i = 0; i < myCount; ++i)
shortData[i] = (u16)data[i];
#endif
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferId);
glCheckErrors();
#if defined(KORE_ANDROID) || defined(KORE_PI)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, myCount * 2, shortData, GL_STATIC_DRAW);
glCheckErrors();
#else
glBufferData(GL_ELEMENT_ARRAY_BUFFER, myCount * 4, data, GL_STATIC_DRAW);
glCheckErrors();
#endif
}
void Graphics3::IndexBuffer::_set() {
current = this;
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferId);
glCheckErrors();
}
void IndexBufferImpl::unset() {
if ((void *)current == (void *)this)
current = nullptr;
}
int Graphics3::IndexBuffer::count() {
return myCount;
}

View File

@ -0,0 +1,24 @@
#pragma once
namespace Kore {
namespace Graphics3 {
class IndexBuffer;
}
class IndexBufferImpl {
protected:
public:
IndexBufferImpl(int count);
void unset();
#if defined(KORE_ANDROID) || defined(KORE_PI)
u16 *shortData;
#endif
int *data;
int myCount;
uint bufferId;
public:
static Graphics3::IndexBuffer *current;
};
}

View File

@ -0,0 +1,100 @@
#include "ogl.h"
#include <Kore/Graphics3/Graphics.h>
#include <Kore/Graphics3/Light.h>
#include <Kore/Math/Core.h>
using namespace Kore;
// OpenGL man pages for "glLight" function:
// see https://www.opengl.org/sdk/docs/man2/xhtml/glLight.xml
LightImpl::LightImpl()
: myType(DirectionalLight), myAmbient(0, 0, 0, 1), myDiffuse(1, 1, 1, 1), mySpecular(1, 1, 1, 1), myPositionOrDirection(0, 0, 1, 0),
mySpotDirection(0, 0, 1), // default point in +Z direction
mySpotExponent(0.0f), mySpotCutoff(180.0f), myConstAttn(1.0f), myLinearAttn(0.0f), myQuadricAttn(0.0f) {}
LightImpl::~LightImpl() {}
void Light::setType(LightType type) {
// Set new light type
myType = type;
// Update position/directior vector
myPositionOrDirection[3] = (myType == DirectionalLight ? 0.0f : 1.0f);
}
void Light::setColors(const vec4 &ambient, const vec4 &diffuse, const vec4 &specular) {
// Store light colors
myAmbient = ambient;
myDiffuse = diffuse;
mySpecular = specular;
}
void Light::setPosition(const vec3 &position) {
// Store position point (x, y, z, 1)
myPositionOrDirection = vec4(position, 1);
}
void Light::setDirection(const vec3 &direction) {
if (myType == SpotLight) {
// Store spot direction vector (x, y, z)
mySpotDirection = direction;
}
else {
// Store direction vector (x, y, z, 0)
myPositionOrDirection = vec4(direction, 0);
}
}
void Light::setSpot(float exponent, float cutoff) {
mySpotExponent = exponent;
mySpotCutoff = cutoff;
}
void Light::setAttenuation(float constAttn, float linearAttn, float quadricAttn) {
myConstAttn = constAttn;
myLinearAttn = linearAttn;
myQuadricAttn = quadricAttn;
}
/*
1
GL Light Intensity = -----------------------------------
constant + d*linear + d^2*quadratic
*/
void Light::setAttenuationRadius(float radius) {
setAttenuation(1.0f, 1.0f / radius, 1.0f / radius);
}
void LightImpl::submitLightParamsToGL(GLenum lightID) const {
// Submit colors
glLightfv(lightID, GL_AMBIENT, myAmbient.values);
glLightfv(lightID, GL_DIFFUSE, myDiffuse.values);
glLightfv(lightID, GL_SPECULAR, mySpecular.values);
// Submit attenuation
glLightf(lightID, GL_CONSTANT_ATTENUATION, myConstAttn);
glLightf(lightID, GL_LINEAR_ATTENUATION, myLinearAttn);
glLightf(lightID, GL_QUADRATIC_ATTENUATION, myQuadricAttn);
// Submit spot parameters
glLightfv(lightID, GL_SPOT_DIRECTION, mySpotDirection.values);
glLightf(lightID, GL_SPOT_EXPONENT, mySpotExponent);
glLightf(lightID, GL_SPOT_CUTOFF, mySpotCutoff);
}
void LightImpl::submitLightTransformToGL(GLenum lightID) const {
glLightfv(lightID, GL_POSITION, myPositionOrDirection.values);
}
Light::Light(LightType type) : LightImpl() {
setType(type);
}
void Light::_set(int num) {
GLenum lightID = GL_LIGHT0 + num;
glEnable(lightID);
submitLightParamsToGL(lightID);
submitLightTransformToGL(lightID);
}

View File

@ -0,0 +1,33 @@
#pragma once
#include "ogl.h"
#include <Kore/Math/Vector.h>
namespace Kore {
enum LightType { DirectionalLight, PointLight, SpotLight };
class LightImpl {
public:
LightImpl();
virtual ~LightImpl();
protected:
// Submit light parameters to OpenGL (lightID is GL_LIGHT<n> where <n> is in the range [0, 7])
void submitLightParamsToGL(GLenum lightID) const;
// Submit light transformation to OpenGL (lightID is GL_LIGHT<n> where <n> is in the range [0, 7]).
void submitLightTransformToGL(GLenum lightID) const;
LightType myType;
vec4 myAmbient;
vec4 myDiffuse;
vec4 mySpecular;
vec4 myPositionOrDirection;
vec3 mySpotDirection;
float mySpotExponent;
float mySpotCutoff;
float myConstAttn;
float myLinearAttn;
float myQuadricAttn;
};
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,5 @@
#pragma once
#include <Kore/Graphics1/Image.h>
#include <Kore/Graphics3/Graphics.h>
#include <Kore/Math/Matrix.h>

View File

@ -0,0 +1,204 @@
#include "ogl.h"
#include <Kore/Graphics3/Graphics.h>
#include <Kore/Graphics4/Shader.h>
#include <Kore/Log.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
using namespace Kore;
namespace Kore {
#ifndef OPENGLES
bool programUsesTessellation = false;
#endif
}
ProgramImpl::ProgramImpl()
: textureCount(0), vertexShader(nullptr), fragmentShader(nullptr), geometryShader(nullptr), tessellationEvaluationShader(nullptr),
tessellationControlShader(nullptr) {
textures = new const char *[16];
textureValues = new int[16];
}
Graphics4::Program::Program() {
programId = glCreateProgram();
glCheckErrors();
}
ProgramImpl::~ProgramImpl() {
glDeleteProgram(programId);
}
void Graphics4::Program::setVertexShader(Shader *shader) {
vertexShader = shader;
}
void Graphics4::Program::setFragmentShader(Shader *shader) {
fragmentShader = shader;
}
void Graphics4::Program::setGeometryShader(Shader *shader) {
#ifndef OPENGLES
geometryShader = shader;
#endif
}
void Graphics4::Program::setTessellationControlShader(Shader *shader) {
#ifndef OPENGLES
tessellationControlShader = shader;
#endif
}
void Graphics4::Program::setTessellationEvaluationShader(Shader *shader) {
#ifndef OPENGLES
tessellationEvaluationShader = shader;
#endif
}
namespace {
int toGlShader(Graphics4::ShaderType type) {
switch (type) {
case Graphics4::VertexShader:
default:
return GL_VERTEX_SHADER;
case Graphics4::FragmentShader:
return GL_FRAGMENT_SHADER;
/*#ifndef OPENGLES
case GeometryShader:
return GL_GEOMETRY_SHADER;
case TessellationControlShader:
return GL_TESS_CONTROL_SHADER;
case TessellationEvaluationShader:
return GL_TESS_EVALUATION_SHADER;
#endif*/
}
}
void compileShader(uint &id, char *source, int length, Graphics4::ShaderType type) {
id = glCreateShader(toGlShader(type));
glCheckErrors();
glShaderSource(id, 1, (const GLchar **)&source, 0);
glCompileShader(id);
int result;
glGetShaderiv(id, GL_COMPILE_STATUS, &result);
if (result != GL_TRUE) {
int length;
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
char *errormessage = new char[length];
glGetShaderInfoLog(id, length, nullptr, errormessage);
printf("GLSL compiler error: %s\n", errormessage);
delete[] errormessage;
}
}
}
void Graphics4::Program::link(VertexStructure **structures, int count) {
compileShader(vertexShader->id, vertexShader->source, vertexShader->length, VertexShader);
compileShader(fragmentShader->id, fragmentShader->source, fragmentShader->length, FragmentShader);
#ifndef OPENGLES
if (geometryShader != nullptr)
compileShader(geometryShader->id, geometryShader->source, geometryShader->length, GeometryShader);
if (tessellationControlShader != nullptr)
compileShader(tessellationControlShader->id, tessellationControlShader->source, tessellationControlShader->length, TessellationControlShader);
if (tessellationEvaluationShader != nullptr)
compileShader(tessellationEvaluationShader->id, tessellationEvaluationShader->source, tessellationEvaluationShader->length,
TessellationEvaluationShader);
#endif
glAttachShader(programId, vertexShader->id);
glAttachShader(programId, fragmentShader->id);
#ifndef OPENGLES
if (geometryShader != nullptr)
glAttachShader(programId, geometryShader->id);
if (tessellationControlShader != nullptr)
glAttachShader(programId, tessellationControlShader->id);
if (tessellationEvaluationShader != nullptr)
glAttachShader(programId, tessellationEvaluationShader->id);
#endif
glCheckErrors();
int index = 0;
for (int i1 = 0; i1 < count; ++i1) {
for (int i2 = 0; i2 < structures[i1]->size; ++i2) {
VertexElement element = structures[i1]->elements[i2];
glBindAttribLocation(programId, index, element.name);
glCheckErrors();
if (element.data == Float4x4VertexData) {
index += 4;
}
else {
++index;
}
}
}
glLinkProgram(programId);
int result;
glGetProgramiv(programId, GL_LINK_STATUS, &result);
if (result != GL_TRUE) {
int length;
glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &length);
char *errormessage = new char[length];
glGetProgramInfoLog(programId, length, nullptr, errormessage);
printf("GLSL linker error: %s\n", errormessage);
delete[] errormessage;
}
#ifndef KORE_OPENGL_ES
#ifndef KORE_LINUX
/* if (tessellationControlShader != nullptr) {
glPatchParameteri(GL_PATCH_VERTICES, 3);
glCheckErrors();
}*/
#endif
#endif
}
void Graphics4::Program::set() {
#ifndef KORE_OPENGL_ES
programUsesTessellation = tessellationControlShader != nullptr;
#endif
glUseProgram(programId);
glCheckErrors();
for (int index = 0; index < textureCount; ++index) {
glUniform1i(textureValues[index], index);
glCheckErrors();
}
}
Graphics4::ConstantLocation Graphics4::Program::getConstantLocation(const char *name) {
ConstantLocation location;
location.location = glGetUniformLocation(programId, name);
glCheckErrors();
if (location.location < 0) {
log(Warning, "Uniform %s not found.", name);
}
return location;
}
int ProgramImpl::findTexture(const char *name) {
for (int index = 0; index < textureCount; ++index) {
if (strcmp(textures[index], name) == 0)
return index;
}
return -1;
}
Graphics4::TextureUnit Graphics4::Program::getTextureUnit(const char *name) {
int index = findTexture(name);
if (index < 0) {
int location = glGetUniformLocation(programId, name);
glCheckErrors();
index = textureCount;
textureValues[index] = location;
textures[index] = name;
++textureCount;
}
TextureUnit unit;
unit.unit = index;
return unit;
}

View File

@ -0,0 +1,29 @@
#pragma once
namespace Kore {
namespace Graphics4 {
class Shader;
}
class ProgramImpl {
protected:
uint programId;
Graphics4::Shader *vertexShader;
Graphics4::Shader *fragmentShader;
Graphics4::Shader *geometryShader;
Graphics4::Shader *tessellationControlShader;
Graphics4::Shader *tessellationEvaluationShader;
ProgramImpl();
virtual ~ProgramImpl();
int findTexture(const char *name);
const char **textures;
int *textureValues;
int textureCount;
};
class ConstantLocationImpl {
public:
int location;
};
}

View File

@ -0,0 +1,236 @@
#include "RenderTargetImpl.h"
#include "ogl.h"
#include <Kore/Graphics3/Graphics.h>
#include <Kore/Log.h>
#include <Kore/System.h>
#ifdef KORE_ANDROID
#include <GLContext.h>
#endif
using namespace Kore;
#ifndef GL_RGBA16F_EXT
#define GL_RGBA16F_EXT 0x881A
#endif
#ifndef GL_RGBA32F_EXT
#define GL_RGBA32F_EXT 0x8814
#endif
#ifndef GL_HALF_FLOAT
#define GL_HALF_FLOAT 0x140B
#endif
namespace {
int pow(int pow) {
int ret = 1;
for (int i = 0; i < pow; ++i)
ret *= 2;
return ret;
}
int getPower2(int i) {
for (int power = 0;; ++power)
if (pow(power) >= i)
return pow(power);
}
bool nonPow2RenderTargetsSupported() {
#ifdef KORE_OPENGL_ES
#ifdef KORE_ANDROID
if (ndk_helper::GLContext::GetInstance()->GetGLVersion() >= 3.0)
return true;
else
return false;
#else
return false;
#endif
#else
return true;
#endif
}
}
void RenderTargetImpl::setupDepthStencil(int depthBufferBits, int stencilBufferBits, int width, int height) {
if (depthBufferBits > 0 && stencilBufferBits > 0) {
#ifdef KORE_OPENGL_ES
GLenum internalFormat = GL_DEPTH24_STENCIL8_OES;
#else
GLenum internalFormat;
if (depthBufferBits == 24)
internalFormat = GL_DEPTH24_STENCIL8;
else
internalFormat = GL_DEPTH32F_STENCIL8;
#endif
// Renderbuffer
// glGenRenderbuffers(1, &_depthRenderbuffer);
// glCheckErrors();
// glBindRenderbuffer(GL_RENDERBUFFER, _depthRenderbuffer);
// glCheckErrors();
// glRenderbufferStorage(GL_RENDERBUFFER, internalFormat, width, height);
// glCheckErrors();
// #ifdef KORE_OPENGL_ES
// glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthRenderbuffer);
// glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _depthRenderbuffer);
// #else
// glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, _depthRenderbuffer);
// #endif
// glCheckErrors();
// Texture
glGenTextures(1, &_depthTexture);
glCheckErrors();
glBindTexture(GL_TEXTURE_2D, _depthTexture);
glCheckErrors();
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0);
glCheckErrors();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glCheckErrors();
glBindFramebuffer(GL_FRAMEBUFFER, _framebuffer);
glCheckErrors();
#ifdef KORE_OPENGL_ES
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _depthTexture, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, _depthTexture, 0);
#else
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, _depthTexture, 0);
#endif
glCheckErrors();
}
else if (depthBufferBits > 0) {
// Renderbuffer
// glGenRenderbuffers(1, &_depthRenderbuffer);
// glCheckErrors();
// glBindRenderbuffer(GL_RENDERBUFFER, _depthRenderbuffer);
// glCheckErrors();
// glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
// glCheckErrors();
// glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthRenderbuffer);
// glCheckErrors();
// Texture
glGenTextures(1, &_depthTexture);
glCheckErrors();
glBindTexture(GL_TEXTURE_2D, _depthTexture);
glCheckErrors();
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0);
glCheckErrors();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glCheckErrors();
glBindFramebuffer(GL_FRAMEBUFFER, _framebuffer);
glCheckErrors();
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _depthTexture, 0);
glCheckErrors();
}
}
Graphics3::RenderTarget::RenderTarget(int width, int height, int depthBufferBits, bool antialiasing, RenderTargetFormat format, int stencilBufferBits,
int contextId)
: width(width), height(height) {
if (nonPow2RenderTargetsSupported()) {
texWidth = width;
texHeight = height;
}
else {
texWidth = getPower2(width);
texHeight = getPower2(height);
}
this->contextId = contextId;
// (DK) required on windows/gl
Kore::System::makeCurrent(contextId);
glGenTextures(1, &_texture);
glCheckErrors();
glBindTexture(GL_TEXTURE_2D, _texture);
glCheckErrors();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glCheckErrors();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glCheckErrors();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glCheckErrors();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glCheckErrors();
switch (format) {
#ifndef KORE_MACOS
case Target128BitFloat:
#ifdef KORE_OPENGL_ES
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F_EXT, texWidth, texHeight, 0, GL_RGBA, GL_FLOAT, 0);
#else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, texWidth, texHeight, 0, GL_RGBA, GL_FLOAT, 0);
#endif
break;
case Target64BitFloat:
#ifdef KORE_OPENGL_ES
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_EXT, texWidth, texHeight, 0, GL_RGBA, GL_HALF_FLOAT, 0);
#else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, texWidth, texHeight, 0, GL_RGBA, GL_HALF_FLOAT, 0);
#endif
break;
case Target16BitDepth:
#ifdef KORE_OPENGL_ES
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
#endif
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, texWidth, texHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0);
break;
case Target32Bit:
#endif
default:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
}
glCheckErrors();
glGenFramebuffers(1, &_framebuffer);
glCheckErrors();
glBindFramebuffer(GL_FRAMEBUFFER, _framebuffer);
glCheckErrors();
setupDepthStencil(depthBufferBits, stencilBufferBits, texWidth, texHeight);
if (format == Target16BitDepth) {
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, _texture, 0);
#ifndef OPENGLES
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
#endif
}
else {
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture, 0);
}
glCheckErrors();
// GLenum drawBuffers[1] = { GL_COLOR_ATTACHMENT0 };
// glDrawBuffers(1, drawBuffers);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glCheckErrors();
glBindTexture(GL_TEXTURE_2D, 0);
glCheckErrors();
}
void Graphics3::RenderTarget::useColorAsTexture(TextureUnit unit) {
glActiveTexture(GL_TEXTURE0 + unit.unit);
glCheckErrors();
glBindTexture(GL_TEXTURE_2D, _texture);
glCheckErrors();
}
void Graphics3::RenderTarget::useDepthAsTexture(TextureUnit unit) {
glActiveTexture(GL_TEXTURE0 + unit.unit);
glCheckErrors();
glBindTexture(GL_TEXTURE_2D, _depthTexture);
glCheckErrors();
}
void Graphics3::RenderTarget::setDepthStencilFrom(RenderTarget *source) {
glBindFramebuffer(GL_FRAMEBUFFER, _framebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, source->_depthTexture, 0);
}

View File

@ -0,0 +1,13 @@
#pragma once
namespace Kore {
class RenderTargetImpl {
public:
unsigned _framebuffer;
unsigned _texture;
unsigned _depthTexture;
// unsigned _depthRenderbuffer;
int contextId;
void setupDepthStencil(int depthBufferBits, int stencilBufferBits, int width, int height);
};
}

View File

@ -0,0 +1,24 @@
#include "ogl.h"
#include <Kore/Graphics3/Graphics.h>
#include <Kore/Graphics4/Shader.h>
#include <Kore/Math/Core.h>
using namespace Kore;
ShaderImpl::ShaderImpl(void *source, int length) : length(length), id(0) {
this->source = new char[length + 1];
for (int i = 0; i < length; ++i) {
this->source[i] = ((char *)source)[i];
}
this->source[length] = 0;
}
ShaderImpl::~ShaderImpl() {
delete[] source;
source = nullptr;
if (id != 0)
glDeleteShader(id);
}
Graphics4::Shader::Shader(void *source, int length, Graphics4::ShaderType type) : ShaderImpl(source, length) {}

View File

@ -0,0 +1,20 @@
#pragma once
namespace Kore {
namespace Graphics4 {
class Program;
}
class ProgramImpl;
class ShaderImpl {
public:
ShaderImpl(void *source, int length);
virtual ~ShaderImpl();
uint id;
char *source;
int length;
friend class Program;
friend class ProgramImpl;
};
}

View File

@ -0,0 +1,444 @@
#include "TextureImpl.h"
#include "ogl.h"
#include <Kore/Graphics1/Image.h>
#include <Kore/Graphics3/Graphics.h>
#include <Kore/Log.h>
using namespace Kore;
#ifndef GL_TEXTURE_3D
#define GL_TEXTURE_3D 0x806F
#endif
namespace {
int convertFormat(Graphics3::Image::Format format) {
switch (format) {
case Graphics3::Image::RGBA32:
case Graphics3::Image::RGBA64:
case Graphics3::Image::RGBA128:
default:
// #ifdef GL_BGRA
// return GL_BGRA;
// #else
return GL_RGBA;
// #endif
case Graphics3::Image::RGB24:
return GL_RGB;
case Graphics3::Image::Grey8:
#ifdef KORE_OPENGL_ES
return GL_LUMINANCE;
#else
return GL_RED;
#endif
}
}
int convertInternalFormat(Graphics3::Image::Format format) {
switch (format) {
case Graphics3::Image::RGBA128:
return GL_RGBA;
case Graphics3::Image::RGBA32:
case Graphics3::Image::RGBA64:
default:
// #ifdef GL_BGRA
// return GL_BGRA;
// #else
return GL_RGBA;
// #endif
case Graphics3::Image::RGB24:
return GL_RGB;
case Graphics3::Image::Grey8:
#ifdef KORE_OPENGL_ES
return GL_LUMINANCE;
#else
return GL_RED;
#endif
}
}
int convertType(Graphics3::Image::Format format) {
switch (format) {
case Graphics3::Image::RGBA128:
case Graphics3::Image::RGBA64:
return GL_FLOAT;
case Graphics3::Image::RGBA32:
default:
return GL_UNSIGNED_BYTE;
}
}
#if 0
int astcFormat(u8 blockX, u8 blockY) {
switch (blockX) {
case 4:
switch (blockY) {
case 4:
return COMPRESSED_RGBA_ASTC_4x4_KHR;
}
case 5:
switch (blockY) {
case 4:
return COMPRESSED_RGBA_ASTC_5x4_KHR;
case 5:
return COMPRESSED_RGBA_ASTC_5x5_KHR;
}
case 6:
switch (blockY) {
case 5:
return COMPRESSED_RGBA_ASTC_6x5_KHR;
case 6:
return COMPRESSED_RGBA_ASTC_6x6_KHR;
}
case 8:
switch (blockY) {
case 5:
return COMPRESSED_RGBA_ASTC_8x5_KHR;
case 6:
return COMPRESSED_RGBA_ASTC_8x6_KHR;
case 8:
return COMPRESSED_RGBA_ASTC_8x8_KHR;
}
case 10:
switch (blockY) {
case 5:
return COMPRESSED_RGBA_ASTC_10x5_KHR;
case 6:
return COMPRESSED_RGBA_ASTC_10x6_KHR;
case 8:
return COMPRESSED_RGBA_ASTC_10x8_KHR;
case 10:
return COMPRESSED_RGBA_ASTC_10x10_KHR;
}
case 12:
switch (blockY) {
case 10:
return COMPRESSED_RGBA_ASTC_12x10_KHR;
case 12:
return COMPRESSED_RGBA_ASTC_12x12_KHR;
}
}
return 0;
}
#endif
int pow(int pow) {
int ret = 1;
for (int i = 0; i < pow; ++i)
ret *= 2;
return ret;
}
int getPower2(int i) {
for (int power = 0;; ++power)
if (pow(power) >= i)
return pow(power);
}
void convertImageToPow2(Graphics3::Image::Format format, u8 *from, int fw, int fh, u8 *to, int tw, int th) {
switch (format) {
case Graphics3::Image::RGBA32:
for (int y = 0; y < th; ++y) {
for (int x = 0; x < tw; ++x) {
to[tw * 4 * y + x * 4 + 0] = 0;
to[tw * 4 * y + x * 4 + 1] = 0;
to[tw * 4 * y + x * 4 + 2] = 0;
to[tw * 4 * y + x * 4 + 3] = 0;
}
}
for (int y = 0; y < fh; ++y) {
for (int x = 0; x < fw; ++x) {
to[tw * 4 * y + x * 4 + 0] = from[y * fw * 4 + x * 4 + 0];
to[tw * 4 * y + x * 4 + 1] = from[y * fw * 4 + x * 4 + 1];
to[tw * 4 * y + x * 4 + 2] = from[y * fw * 4 + x * 4 + 2];
to[tw * 4 * y + x * 4 + 3] = from[y * fw * 4 + x * 4 + 3];
}
}
break;
case Graphics3::Image::Grey8:
for (int y = 0; y < th; ++y) {
for (int x = 0; x < tw; ++x) {
to[tw * y + x] = 0;
}
}
for (int y = 0; y < fh; ++y) {
for (int x = 0; x < fw; ++x) {
to[tw * y + x] = from[y * fw + x];
}
}
break;
}
}
}
void Graphics3::Texture::init(const char *format, bool readable) {
bool toPow2;
if (Graphics3::nonPow2TexturesSupported()) {
texWidth = width;
texHeight = height;
toPow2 = false;
}
else {
texWidth = getPower2(width);
texHeight = getPower2(height);
toPow2 = !(texWidth == width && texHeight == height);
}
u8 *conversionBuffer = nullptr;
if (compressed) {
#if defined(KORE_IOS)
texWidth = Kore::max(texWidth, texHeight);
texHeight = Kore::max(texWidth, texHeight);
if (texWidth < 8)
texWidth = 8;
if (texHeight < 8)
texHeight = 8;
#elif defined(KORE_ANDROID)
texWidth = width;
texHeight = height;
#endif
}
else if (toPow2) {
conversionBuffer = new u8[texWidth * texHeight * sizeOf(this->format)];
convertImageToPow2(this->format, (u8 *)data, width, height, conversionBuffer, texWidth, texHeight);
}
#ifdef KORE_ANDROID
external_oes = false;
#endif
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glCheckErrors();
glGenTextures(1, &texture);
glCheckErrors();
glBindTexture(GL_TEXTURE_2D, texture);
glCheckErrors();
int convertedType = convertType(this->format);
bool isHdr = convertedType == GL_FLOAT;
if (compressed) {
#ifdef KORE_IOS
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, texWidth, texHeight, 0, texWidth * texHeight / 2, data);
// #elif defined(KORE_ANDROID)
// u8 blockX = internalFormat >> 8;
// u8 blockY = internalFormat & 0xff;
// glCompressedTexImage2D(GL_TEXTURE_2D, 0, astcFormat(blockX, blockY), texWidth, texHeight, 0, dataSize, data);
#endif
}
else {
if (isHdr) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, convertedType, hdrData);
}
else {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, convertedType, toPow2 ? conversionBuffer : data);
}
glCheckErrors();
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glCheckErrors();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glCheckErrors();
if (toPow2) {
delete[] conversionBuffer;
conversionBuffer = nullptr;
}
if (!readable) {
if (isHdr) {
delete[] hdrData;
hdrData = nullptr;
}
else {
delete[] data;
data = nullptr;
}
}
if (readable && compressed) {
log(Kore::Warning, "Compressed images can not be readable.");
}
}
Graphics3::Texture::Texture(int width, int height, Image::Format format, bool readable) : Image(width, height, format, readable) {
#ifdef KORE_IOS
texWidth = width;
texHeight = height;
#else
if (Graphics3::nonPow2TexturesSupported()) {
texWidth = width;
texHeight = height;
}
else {
texWidth = getPower2(width);
texHeight = getPower2(height);
}
#endif
// conversionBuffer = new u8[texWidth * texHeight * 4];
#ifdef KORE_ANDROID
external_oes = false;
#endif
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glCheckErrors();
glGenTextures(1, &texture);
glCheckErrors();
glBindTexture(GL_TEXTURE_2D, texture);
glCheckErrors();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glCheckErrors();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glCheckErrors();
if (convertType(format) == GL_FLOAT) {
glTexImage2D(GL_TEXTURE_2D, 0, convertInternalFormat(format), texWidth, texHeight, 0, convertFormat(format), GL_FLOAT, nullptr);
}
else {
glTexImage2D(GL_TEXTURE_2D, 0, convertInternalFormat(format), texWidth, texHeight, 0, convertFormat(format), GL_UNSIGNED_BYTE, data);
}
glCheckErrors();
/*if (!readable) {
delete[] data;
data = nullptr;
}*/
}
Graphics3::Texture::Texture(int width, int height, int depth, Graphics3::Image::Format format, bool readable) : Image(width, height, depth, format, readable) {
#ifndef OPENGLES
glGenTextures(1, &texture);
glCheckErrors();
glBindTexture(GL_TEXTURE_3D, texture);
glCheckErrors();
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glCheckErrors();
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glCheckErrors();
glTexImage3D(GL_TEXTURE_3D, 0, convertFormat(format), width, height, depth, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glCheckErrors();
#endif
}
#ifdef KORE_ANDROID
Texture::Texture(unsigned texid) : Image(1023, 684, Image::RGBA32, false) {
texture = texid;
external_oes = true;
texWidth = 1023;
texHeight = 684;
}
#endif
TextureImpl::~TextureImpl() {
glDeleteTextures(1, &texture);
glFlush();
}
void Graphics3::Texture::_set(TextureUnit unit) {
GLenum target = depth > 1 ? GL_TEXTURE_3D : GL_TEXTURE_2D;
glActiveTexture(GL_TEXTURE0 + unit.unit);
glCheckErrors();
#ifdef KORE_ANDROID
if (external_oes) {
glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture);
glCheckErrors();
}
else {
glBindTexture(target, texture);
glCheckErrors();
}
#else
glBindTexture(target, texture);
glCheckErrors();
#endif
}
int Graphics3::Texture::stride() {
return width * sizeOf(format);
}
u8 *Graphics3::Texture::lock() {
return (u8 *)data;
}
/*void Texture::unlock() {
if (conversionBuffer != nullptr) {
convertImageToPow2(format, (u8*)data, width, height, conversionBuffer, texWidth, texHeight);
glBindTexture(GL_TEXTURE_2D, texture);
#ifndef GL_LUMINANCE
#define GL_LUMINANCE GL_RED
#endif
glTexImage2D(GL_TEXTURE_2D, 0, (format == Image::RGBA32) ? GL_RGBA : GL_LUMINANCE, texWidth, texHeight, 0, (format == Image::RGBA32) ? GL_RGBA :
GL_LUMINANCE, GL_UNSIGNED_BYTE, conversionBuffer);
}
}*/
void Graphics3::Texture::unlock() {
// if (conversionBuffer != nullptr) {
// convertImageToPow2(format, (u8*)data, width, height, conversionBuffer, texWidth, texHeight);
glBindTexture(GL_TEXTURE_2D, texture);
glCheckErrors();
// glTexImage2D(GL_TEXTURE_2D, 0, (format == Image::RGBA32) ? GL_RGBA : GL_LUMINANCE, texWidth, texHeight, 0, (format == Image::RGBA32) ? GL_RGBA :
// GL_LUMINANCE, GL_UNSIGNED_BYTE, conversionBuffer);
if (convertType(format) == GL_FLOAT) {
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texWidth, texHeight, convertFormat(format), GL_FLOAT, hdrData);
glCheckErrors();
}
else {
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texWidth, texHeight, convertFormat(format), GL_UNSIGNED_BYTE, data);
glCheckErrors();
}
// }
}
void Graphics3::Texture::clear(int x, int y, int z, int width, int height, int depth, uint color) {
#ifdef GL_VERSION_4_4
static float clearColor[4];
clearColor[0] = ((color & 0x00ff0000) >> 16) / 255.0f;
clearColor[1] = ((color & 0x0000ff00) >> 8) / 255.0f;
clearColor[2] = (color & 0x000000ff) / 255.0f;
clearColor[3] = ((color & 0xff000000) >> 24) / 255.0f;
GLenum target = depth > 1 ? GL_TEXTURE_3D : GL_TEXTURE_2D;
glBindTexture(target, texture);
glClearTexSubImage(texture, 0, x, y, z, width, height, depth, convertFormat(format), convertType(format), clearColor);
#endif
}
#ifdef KORE_IOS
void Texture::upload(u8 *data) {
glBindTexture(GL_TEXTURE_2D, texture);
glCheckErrors();
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texWidth, texHeight, convertFormat(format), GL_UNSIGNED_BYTE, data);
glCheckErrors();
}
#endif
void Graphics3::Texture::generateMipmaps(int levels) {
GLenum target = depth > 1 ? GL_TEXTURE_3D : GL_TEXTURE_2D;
glBindTexture(target, texture);
glCheckErrors();
glGenerateMipmap(target);
glCheckErrors();
}
void Graphics3::Texture::setMipmap(Texture *mipmap, int level) {
int convertedType = convertType(mipmap->format);
bool isHdr = convertedType == GL_FLOAT;
GLenum target = depth > 1 ? GL_TEXTURE_3D : GL_TEXTURE_2D;
glBindTexture(target, texture);
glCheckErrors();
if (isHdr) {
glTexImage2D(target, level, convertInternalFormat(mipmap->format), mipmap->texWidth, mipmap->texHeight, 0, convertFormat(mipmap->format), convertedType,
mipmap->hdrData);
glCheckErrors();
}
else {
glTexImage2D(target, level, convertInternalFormat(mipmap->format), mipmap->texWidth, mipmap->texHeight, 0, convertFormat(mipmap->format), convertedType,
mipmap->data);
glCheckErrors();
}
}

View File

@ -0,0 +1,28 @@
#pragma once
#include <Kore/Graphics1/Image.h>
namespace Kore {
namespace Graphics3 {
class Texture;
}
class TextureUnitImpl {
public:
int unit;
};
class TextureImpl {
protected:
// static TreeMap<Image, Texture*> images;
public:
unsigned int texture;
#ifdef KORE_ANDROID
bool external_oes;
#endif
u8 pixfmt;
~TextureImpl();
};
}

View File

@ -0,0 +1,245 @@
#include "VertexBufferImpl.h"
#include <Kore/Graphics3/Graphics.h>
#include "ShaderImpl.h"
#include "ogl.h"
#include <assert.h>
using namespace Kore;
Graphics3::VertexBuffer *VertexBufferImpl::current = nullptr;
VertexBufferImpl::VertexBufferImpl(int count, int instanceDataStepRate) : myCount(count), instanceDataStepRate(instanceDataStepRate) {
#ifndef NDEBUG
initialized = false;
#endif
}
Graphics3::VertexBuffer::VertexBuffer(int vertexCount, const Graphics4::VertexStructure &structure, Usage usage, int instanceDataStepRate)
: VertexBufferImpl(vertexCount, instanceDataStepRate) {
myStride = 0;
for (int i = 0; i < structure.size; ++i) {
Graphics4::VertexElement element = structure.elements[i];
switch (element.data) {
case Graphics4::ColorVertexData:
myStride += 1 * 4;
break;
case Graphics4::Float1VertexData:
myStride += 1 * 4;
break;
case Graphics4::Float2VertexData:
myStride += 2 * 4;
break;
case Graphics4::Float3VertexData:
myStride += 3 * 4;
break;
case Graphics4::Float4VertexData:
myStride += 4 * 4;
break;
case Graphics4::Float4x4VertexData:
myStride += 4 * 4 * 4;
break;
}
}
this->structure = structure;
glGenBuffers(1, &bufferId);
glCheckErrors();
data = new float[vertexCount * myStride / 4];
}
Graphics3::VertexBuffer::~VertexBuffer() {
unset();
delete[] data;
}
float *Graphics3::VertexBuffer::lock() {
return data;
}
/*
// TODO: FIXME!
float* VertexBuffer::lock(int start, int count) {
myCount = count;
return nullptr;//&buffer[start * 9];
}
*/
void Graphics3::VertexBuffer::unlock() {
glBindBuffer(GL_ARRAY_BUFFER, bufferId);
glCheckErrors();
glBufferData(GL_ARRAY_BUFFER, myStride * myCount, data, GL_STATIC_DRAW);
glCheckErrors();
#ifndef NDEBUG
initialized = true;
#endif
}
int Graphics3::VertexBuffer::_set(int offset) {
assert(initialized); // Vertex Buffer is used before lock/unlock was called
int offsetoffset = setVertexAttributes(offset);
if (IndexBuffer::current != nullptr)
IndexBuffer::current->_set();
return offsetoffset;
}
void VertexBufferImpl::unset() {
if ((void *)current == (void *)this)
current = nullptr;
}
int Graphics3::VertexBuffer::count() {
return myCount;
}
int Graphics3::VertexBuffer::stride() {
return myStride;
}
int VertexBufferImpl::setVertexAttributes(int offset) {
glBindBuffer(GL_ARRAY_BUFFER, bufferId);
glCheckErrors();
// Enable vertex attributes
unsigned int usedAttribsMask = 0;
int internaloffset = 0;
int actualIndex = 0;
for (int index = 0; index < structure.size; ++index) {
Graphics4::VertexElement element = structure.elements[index];
int size = 0;
GLenum type = GL_FLOAT;
switch (element.data) {
case Graphics4::ColorVertexData:
size = 4;
type = GL_UNSIGNED_BYTE;
break;
case Graphics4::Float1VertexData:
size = 1;
break;
case Graphics4::Float2VertexData:
size = 2;
break;
case Graphics4::Float3VertexData:
size = 3;
break;
case Graphics4::Float4VertexData:
size = 4;
break;
case Graphics4::Float4x4VertexData:
size = 16;
break;
}
switch (element.attribute) {
case Graphics4::VertexCoord:
assert(size >= 2 && size <= 4);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(size, type, myStride, reinterpret_cast<const void *>(internaloffset));
break;
case Graphics4::VertexNormal:
assert(size == 3);
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(type, myStride, reinterpret_cast<const void *>(internaloffset));
break;
case Graphics4::VertexColor0:
assert(size >= 3 && size <= 4);
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(size, type, myStride, reinterpret_cast<const void *>(internaloffset));
break;
case Graphics4::VertexColor1:
assert(size == 3);
glEnableClientState(GL_SECONDARY_COLOR_ARRAY);
glSecondaryColorPointer(size, type, myStride, reinterpret_cast<const void *>(internaloffset));
break;
case Graphics4::VertexTexCoord0:
case Graphics4::VertexTexCoord1:
case Graphics4::VertexTexCoord2:
case Graphics4::VertexTexCoord3:
case Graphics4::VertexTexCoord4:
case Graphics4::VertexTexCoord5:
case Graphics4::VertexTexCoord6:
case Graphics4::VertexTexCoord7:
assert(size >= 1 && size <= 4);
glClientActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(element.attribute - Graphics4::VertexTexCoord0));
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(size, type, myStride, reinterpret_cast<const void *>(internaloffset));
break;
default:
break;
}
usedAttribsMask |= (1u << element.attribute);
++actualIndex;
switch (element.data) {
case Graphics4::ColorVertexData:
internaloffset += 4 * 1;
break;
case Graphics4::Float1VertexData:
internaloffset += 4 * 1;
break;
case Graphics4::Float2VertexData:
internaloffset += 4 * 2;
break;
case Graphics4::Float3VertexData:
internaloffset += 4 * 3;
break;
case Graphics4::Float4VertexData:
internaloffset += 4 * 4;
break;
case Graphics4::Float4x4VertexData:
internaloffset += 4 * 4 * 4;
break;
}
}
// Disable unused vertex attributes
for (int attrib = Graphics4::VertexCoord; attrib <= Graphics4::VertexTexCoord7; ++attrib) {
if ((usedAttribsMask & (1u << attrib)) == 0) {
switch (attrib) {
case Graphics4::VertexCoord:
glDisableClientState(GL_VERTEX_ARRAY);
break;
case Graphics4::VertexNormal:
glDisableClientState(GL_NORMAL_ARRAY);
break;
case Graphics4::VertexColor0:
glDisableClientState(GL_COLOR_ARRAY);
break;
case Graphics4::VertexColor1:
glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
break;
case Graphics4::VertexTexCoord0:
case Graphics4::VertexTexCoord1:
case Graphics4::VertexTexCoord2:
case Graphics4::VertexTexCoord3:
case Graphics4::VertexTexCoord4:
case Graphics4::VertexTexCoord5:
case Graphics4::VertexTexCoord6:
case Graphics4::VertexTexCoord7:
glClientActiveTexture(GL_TEXTURE0 + static_cast<GLenum>(attrib - Graphics4::VertexTexCoord0));
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
break;
default:
break;
}
}
glCheckErrors();
}
return actualIndex;
}

View File

@ -0,0 +1,29 @@
#pragma once
#include <Kore/Graphics4/VertexStructure.h>
namespace Kore {
namespace Graphics3 {
class VertexBuffer;
}
class VertexBufferImpl {
protected:
VertexBufferImpl(int count, int instanceDataStepRate);
void unset();
float *data;
int myCount;
int myStride;
uint bufferId;
// #if defined KORE_ANDROID || defined KORE_EMSCRIPTEN || defined KORE_TIZEN
Graphics4::VertexStructure structure;
// #endif
int instanceDataStepRate;
int setVertexAttributes(int offset);
#ifndef NDEBUG
bool initialized;
#endif
public:
static Graphics3::VertexBuffer *current;
};
}

View File

@ -0,0 +1,75 @@
#pragma once
#ifdef KORE_WINDOWS
#include <GL/gl.h>
#include <GL/glew.h>
#endif
#ifdef KORE_MACOS
#include <OpenGL/gl.h>
#include <OpenGL/glext.h>
#endif
#ifdef KORE_IOS
#import <OpenGLES/ES2/gl.h>
#import <OpenGLES/ES2/glext.h>
#import <OpenGLES/ES3/gl.h>
#endif
#ifdef KORE_ANDROID
#include <EGL/egl.h>
#if KORE_ANDROID_API >= 18
#include <GLES3/gl3.h>
#endif
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#endif
#ifdef KORE_EMSCRIPTEN
#define GL_GLEXT_PROTOTYPES
#define EGL_EGLEXT_PROTOTYPES
#include <GL/gl.h>
#endif
#ifdef KORE_LINUX
#include <X11/X.h>
#include <X11/Xlib.h>
#define GL_GLEXT_PROTOTYPES
#include <GL/gl.h>
#include <GL/glext.h>
#include <GL/glx.h>
#endif
#ifdef KORE_PI
// #define GL_GLEXT_PROTOTYPES
#include "EGL/egl.h"
#include "EGL/eglext.h"
#include "GLES2/gl2.h"
#endif
#ifdef KORE_TIZEN
#include <gl2.h>
#endif
#include <Kore/Log.h>
#if defined(NDEBUG) || defined(KORE_OSX) || defined(KORE_IOS) || defined(KORE_ANDROID) || 1 // Calling glGetError too early means trouble
#define glCheckErrors() \
{}
#else
#define glCheckErrors() \
{ \
GLenum code = glGetError(); \
while (code != GL_NO_ERROR) { \
Kore::log(Kore::Error, "GL Error %d %s %d\n", code, __FILE__, __LINE__); \
} \
}
#endif
#define glCheckErrors2() \
{ \
GLenum code = glGetError(); \
while (code != GL_NO_ERROR) { \
Kore::log(Kore::Error, "GL Error %d %s %d\n", code, __FILE__, __LINE__); \
} \
}

View File

@ -0,0 +1,491 @@
#ifdef KORE_OCULUS
#include <kinc/vr/vrinterface.h>
#include "Direct3D11.h"
#include <Kore/Graphics4/Graphics.h>
#include <kinc/log.h>
#include "OVR_CAPI_D3D.h"
#include "d3d11.h"
#include <vector>
#if _MSC_VER > 1600
#include "DirectXMath.h"
using namespace DirectX;
#else
#include "xnamath.h"
#endif //_MSC_VER > 1600
#pragma comment(lib, "dxgi.lib")
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "d3dcompiler.lib")
using namespace Kore;
namespace {
kinc_vr_sensor_state_t sensorStates[2];
}
//------------------------------------------------------------
struct DepthBuffer {
ID3D11DepthStencilView *TexDsv;
DepthBuffer(ID3D11Device *Device, int sizeW, int sizeH, int sampleCount = 1) {
DXGI_FORMAT format = DXGI_FORMAT_D32_FLOAT;
D3D11_TEXTURE2D_DESC dsDesc;
dsDesc.Width = sizeW;
dsDesc.Height = sizeH;
dsDesc.MipLevels = 1;
dsDesc.ArraySize = 1;
dsDesc.Format = format;
dsDesc.SampleDesc.Count = sampleCount;
dsDesc.SampleDesc.Quality = 0;
dsDesc.Usage = D3D11_USAGE_DEFAULT;
dsDesc.CPUAccessFlags = 0;
dsDesc.MiscFlags = 0;
dsDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
ID3D11Texture2D *Tex;
Device->CreateTexture2D(&dsDesc, nullptr, &Tex);
Device->CreateDepthStencilView(Tex, nullptr, &TexDsv);
Tex->Release();
}
~DepthBuffer() {
TexDsv->Release();
TexDsv = nullptr;
}
};
//-----------------------------------------------------------
struct Camera {
XMVECTOR Pos;
XMVECTOR Rot;
Camera(){};
Camera(XMVECTOR *pos, XMVECTOR *rot) : Pos(*pos), Rot(*rot){};
Camera(const XMVECTOR &pos, const XMVECTOR &rot) : Pos(pos), Rot(rot){};
XMMATRIX GetViewMatrix() {
XMVECTOR forward = XMVector3Rotate(XMVectorSet(0, 0, -1, 0), Rot);
return (XMMatrixLookAtRH(Pos, XMVectorAdd(Pos, forward), XMVector3Rotate(XMVectorSet(0, 1, 0, 0), Rot)));
}
static void *operator new(std::size_t size) {
UNREFERENCED_PARAMETER(size);
return _aligned_malloc(sizeof(Camera), __alignof(Camera));
}
static void operator delete(void *p) {
_aligned_free(p);
}
};
//---------------------------------------------------------------------
struct DirectX11 {
HWND Window;
bool Running;
int WinSizeW;
int WinSizeH;
HINSTANCE hInstance;
DirectX11() : Window(nullptr), Running(false), WinSizeW(0), WinSizeH(0), hInstance(nullptr) {}
~DirectX11() {
ReleaseDevice();
CloseWindow();
}
bool InitWindow(HINSTANCE hinst, const char *title, const char *windowClassName) {
hInstance = hinst;
Running = true;
// Adjust the window size and show at InitDevice time
wchar_t wchTitle[256];
MultiByteToWideChar(CP_ACP, 0, title, -1, wchTitle, 256);
wchar_t wchClassName[256];
MultiByteToWideChar(CP_ACP, 0, windowClassName, -1, wchClassName, 256);
Window = CreateWindowW(wchClassName, wchTitle, WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, 0, 0, hinst, 0);
if (!Window)
return false;
SetWindowLongPtr(Window, 0, LONG_PTR(this));
return true;
}
void CloseWindow() {
if (Window) {
Window = nullptr;
}
}
bool InitDevice(int vpW, int vpH, const LUID *pLuid, bool windowed = true, int scale = 1) {
WinSizeW = vpW;
WinSizeH = vpH;
if (scale == 0)
scale = 1;
RECT size = {0, 0, vpW / scale, vpH / scale};
AdjustWindowRect(&size, WS_OVERLAPPEDWINDOW, false);
const UINT flags = SWP_NOMOVE | SWP_NOZORDER | SWP_SHOWWINDOW;
if (!SetWindowPos(Window, nullptr, 0, 0, size.right - size.left, size.bottom - size.top, flags))
return false;
return true;
}
void SetAndClearRenderTarget(ID3D11RenderTargetView *rendertarget, DepthBuffer *depthbuffer, float R = 0, float G = 0, float B = 0, float A = 0) {
float black[] = {R, G, B, A}; // Important that alpha=0, if want pixels to be transparent, for manual layers
dx_ctx.context->OMSetRenderTargets(1, &rendertarget, (depthbuffer ? depthbuffer->TexDsv : nullptr));
dx_ctx.context->ClearRenderTargetView(rendertarget, black);
if (depthbuffer)
dx_ctx.context->ClearDepthStencilView(depthbuffer->TexDsv, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1, 0);
}
void SetViewport(float vpX, float vpY, float vpW, float vpH) {
D3D11_VIEWPORT D3Dvp;
D3Dvp.Width = vpW;
D3Dvp.Height = vpH;
D3Dvp.MinDepth = 0;
D3Dvp.MaxDepth = 1;
D3Dvp.TopLeftX = vpX;
D3Dvp.TopLeftY = vpY;
dx_ctx.context->RSSetViewports(1, &D3Dvp);
}
void ReleaseDevice() {}
};
static DirectX11 Platform;
//---------------------------------------------------------------------
// ovrSwapTextureSet wrapper class that also maintains the render target views needed for D3D11 rendering.
struct OculusTexture {
ovrSession Session;
ovrTextureSwapChain TextureChain;
std::vector<ID3D11RenderTargetView *> TexRtv;
OculusTexture(ovrSession session, int sizeW, int sizeH, int sampleCount = 1) : Session(session), TextureChain(nullptr) {
ovrTextureSwapChainDesc desc = {};
desc.Type = ovrTexture_2D;
desc.ArraySize = 1;
desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
desc.Width = sizeW;
desc.Height = sizeH;
desc.MipLevels = 1;
desc.SampleCount = sampleCount;
desc.MiscFlags = ovrTextureMisc_DX_Typeless | ovrTextureMisc_AutoGenerateMips;
desc.BindFlags = ovrTextureBind_DX_RenderTarget;
desc.StaticImage = ovrFalse;
ovrResult result = ovr_CreateTextureSwapChainDX(session, dx_ctx.device, &desc, &TextureChain);
int textureCount = 0;
ovr_GetTextureSwapChainLength(Session, TextureChain, &textureCount);
if (OVR_SUCCESS(result)) {
for (int i = 0; i < textureCount; ++i) {
ID3D11Texture2D *tex = nullptr;
ovr_GetTextureSwapChainBufferDX(Session, TextureChain, i, IID_PPV_ARGS(&tex));
D3D11_RENDER_TARGET_VIEW_DESC rtvd = {};
rtvd.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
rtvd.ViewDimension = (sampleCount > 1) ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
ID3D11RenderTargetView *rtv;
dx_ctx.device->CreateRenderTargetView(tex, &rtvd, &rtv);
TexRtv.push_back(rtv);
tex->Release();
}
}
}
~OculusTexture() {
for (int i = 0; i < (int)TexRtv.size(); ++i) {
TexRtv[i]->Release();
TexRtv[i] = nullptr;
}
if (TextureChain) {
ovr_DestroyTextureSwapChain(Session, TextureChain);
TextureChain = nullptr;
}
}
ID3D11RenderTargetView *GetRTV() {
int index = 0;
ovr_GetTextureSwapChainCurrentIndex(Session, TextureChain, &index);
return TexRtv[index];
}
void Commit() {
ovr_CommitTextureSwapChain(Session, TextureChain);
}
};
//---------------------------------------------------------------------
namespace {
// Initialize these to nullptr here to handle dx_ctx.device lost failures cleanly
ovrMirrorTexture mirrorTexture = nullptr;
OculusTexture *pEyeRenderTexture[2] = {nullptr, nullptr};
DepthBuffer *pEyeDepthBuffer[2] = {nullptr, nullptr};
ovrSizei windowSize;
long long frameIndex = 0;
int msaaRate = 4;
bool isVisible = true;
ovrSession session;
ovrHmdDesc hmdDesc;
ovrPosef EyeRenderPose[2];
double sensorSampleTime;
// Make the eye render buffers (caution if actual size < requested due to HW limits).
ovrRecti eyeRenderViewport[2];
void done() {
if (mirrorTexture)
ovr_DestroyMirrorTexture(session, mirrorTexture);
for (int eye = 0; eye < 2; ++eye) {
delete pEyeRenderTexture[eye];
delete pEyeDepthBuffer[eye];
}
Platform.ReleaseDevice();
ovr_Destroy(session);
}
void createOculusTexture() {
// Create mirror texture
ovrMirrorTextureDesc mirrorDesc;
memset(&mirrorDesc, 0, sizeof(mirrorDesc));
mirrorDesc.Width = Platform.WinSizeW;
mirrorDesc.Height = Platform.WinSizeH;
mirrorDesc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
mirrorDesc.MirrorOptions = ovrMirrorOption_Default;
HRESULT result = ovr_CreateMirrorTextureWithOptionsDX(session, dx_ctx.device, &mirrorDesc, &mirrorTexture);
if (!OVR_SUCCESS(result)) {
kinc_log(KINC_LOG_LEVEL_ERROR, "Failed to create mirror texture.");
done();
}
// Make eye render buffers
for (int eye = 0; eye < 2; ++eye) {
ovrSizei idealSize = ovr_GetFovTextureSize(session, ovrEyeType(eye), hmdDesc.DefaultEyeFov[eye], 1);
pEyeRenderTexture[eye] = new OculusTexture(session, idealSize.w, idealSize.h);
pEyeDepthBuffer[eye] = new DepthBuffer(dx_ctx.device, idealSize.w, idealSize.h);
eyeRenderViewport[eye].Pos.x = 0;
eyeRenderViewport[eye].Pos.y = 0;
eyeRenderViewport[eye].Size = idealSize;
if (!pEyeRenderTexture[eye]->TextureChain) {
kinc_log(KINC_LOG_LEVEL_ERROR, "Failed to create texture.");
done();
}
}
}
}
void *kinc_vr_interface_init(void *hinst, const char *title, const char *windowClassName) {
// Initializes LibOVR, and the Rift
ovrInitParams initParams = {ovrInit_RequestVersion | ovrInit_FocusAware, OVR_MINOR_VERSION, NULL, 0, 0};
ovrResult result = ovr_Initialize(&initParams);
if (!OVR_SUCCESS(result)) {
kinc_log(KINC_LOG_LEVEL_ERROR, "Failed to initialize libOVR.");
return (0);
}
if (!Platform.InitWindow((HINSTANCE)hinst, title, windowClassName)) {
kinc_log(KINC_LOG_LEVEL_ERROR, "Failed to open window.");
return (0);
}
ovrGraphicsLuid luid;
result = ovr_Create(&session, &luid);
if (!OVR_SUCCESS(result)) {
kinc_log(KINC_LOG_LEVEL_ERROR, "HMD not connected.");
return false; // TODO: retry
}
hmdDesc = ovr_GetHmdDesc(session);
// Setup Window and Graphics
// Note: the mirror window can be any size, for this sample we use 1/2 the HMD resolution
windowSize = {hmdDesc.Resolution.w / 2, hmdDesc.Resolution.h / 2};
if (!Platform.InitDevice(windowSize.w, windowSize.h, reinterpret_cast<LUID *>(&luid))) {
kinc_log(KINC_LOG_LEVEL_ERROR, "Failed to init dx_ctx.device.");
done();
}
// FloorLevel will give tracking poses where the floor height is 0
ovr_SetTrackingOriginType(session, ovrTrackingOrigin_FloorLevel);
// Return window
return Platform.Window;
}
void kinc_vr_interface_begin() {
// Call ovr_GetRenderDesc each frame to get the ovrEyeRenderDesc, as the returned values (e.g. HmdToEyeOffset) may change at runtime.
ovrEyeRenderDesc eyeRenderDesc[2];
eyeRenderDesc[0] = ovr_GetRenderDesc(session, ovrEye_Left, hmdDesc.DefaultEyeFov[0]);
eyeRenderDesc[1] = ovr_GetRenderDesc(session, ovrEye_Right, hmdDesc.DefaultEyeFov[1]);
// Get both eye poses simultaneously, with IPD offset already included.
ovrPosef HmdToEyePose[2] = {eyeRenderDesc[0].HmdToEyePose, eyeRenderDesc[1].HmdToEyePose};
ovr_GetEyePoses(session, frameIndex, ovrTrue, HmdToEyePose, EyeRenderPose, &sensorSampleTime);
}
void kinc_vr_interface_begin_render(int eye) {
if (pEyeRenderTexture[0] == nullptr || pEyeRenderTexture[1] == nullptr)
createOculusTexture();
// Clear and set up rendertarget
Platform.SetAndClearRenderTarget(pEyeRenderTexture[eye]->GetRTV(), pEyeDepthBuffer[eye]);
Platform.SetViewport((float)eyeRenderViewport[eye].Pos.x, (float)eyeRenderViewport[eye].Pos.y, (float)eyeRenderViewport[eye].Size.w,
(float)eyeRenderViewport[eye].Size.h);
}
void kinc_vr_interface_end_render(int eye) {
// Commit rendering to the swap chain
pEyeRenderTexture[eye]->Commit();
}
namespace {
kinc_matrix4x4_t convert(XMMATRIX &m) {
XMFLOAT4X4 fView;
XMStoreFloat4x4(&fView, m);
kinc_matrix4x4_t mat;
kinc_matrix4x4_set(&mat, 0, 0, fView._11);
kinc_matrix4x4_set(&mat, 0, 1, fView._12);
kinc_matrix4x4_set(&mat, 0, 2, fView._13);
kinc_matrix4x4_set(&mat, 0, 3, fView._14);
kinc_matrix4x4_set(&mat, 1, 0, fView._21);
kinc_matrix4x4_set(&mat, 1, 1, fView._22);
kinc_matrix4x4_set(&mat, 1, 2, fView._23);
kinc_matrix4x4_set(&mat, 1, 3, fView._24);
kinc_matrix4x4_set(&mat, 2, 0, fView._31);
kinc_matrix4x4_set(&mat, 2, 1, fView._32);
kinc_matrix4x4_set(&mat, 2, 2, fView._33);
kinc_matrix4x4_set(&mat, 2, 3, fView._34);
kinc_matrix4x4_set(&mat, 3, 0, fView._41);
kinc_matrix4x4_set(&mat, 3, 1, fView._42);
kinc_matrix4x4_set(&mat, 3, 2, fView._43);
kinc_matrix4x4_set(&mat, 3, 3, fView._44);
return mat;
}
}
kinc_vr_sensor_state_t kinc_vr_interface_get_sensor_state(int eye) {
kinc_vr_pose_state_t poseState;
ovrQuatf orientation = EyeRenderPose[eye].Orientation;
poseState.vrPose.orientation.x = orientation.x;
poseState.vrPose.orientation.y = orientation.y;
poseState.vrPose.orientation.z = orientation.z;
poseState.vrPose.orientation.w = orientation.w;
ovrVector3f pos = EyeRenderPose[eye].Position;
poseState.vrPose.position.x = pos.x;
poseState.vrPose.position.y = pos.y;
poseState.vrPose.position.z = pos.z;
ovrFovPort fov = hmdDesc.DefaultEyeFov[eye];
poseState.vrPose.left = fov.LeftTan;
poseState.vrPose.right = fov.RightTan;
poseState.vrPose.bottom = fov.DownTan;
poseState.vrPose.top = fov.UpTan;
// Get the pose information in XM format
XMVECTOR eyeQuat = XMVectorSet(orientation.x, orientation.y, orientation.z, orientation.w);
XMVECTOR eyePos = XMVectorSet(pos.x, pos.y, pos.z, 0);
// Get view and projection matrices for the Rift camera
Camera finalCam(eyePos, eyeQuat);
XMMATRIX view = finalCam.GetViewMatrix();
ovrMatrix4f p = ovrMatrix4f_Projection(fov, 0.2f, 1000.0f, ovrProjection_None);
XMMATRIX proj = XMMatrixSet(p.M[0][0], p.M[1][0], p.M[2][0], p.M[3][0], p.M[0][1], p.M[1][1], p.M[2][1], p.M[3][1], p.M[0][2], p.M[1][2], p.M[2][2],
p.M[3][2], p.M[0][3], p.M[1][3], p.M[2][3], p.M[3][3]);
poseState.vrPose.eye = convert(view);
kinc_matrix4x4_transpose(&poseState.vrPose.eye);
poseState.vrPose.projection = convert(proj);
kinc_matrix4x4_transpose(&poseState.vrPose.projection);
ovrSessionStatus sessionStatus;
ovr_GetSessionStatus(session, &sessionStatus);
poseState.isVisible = sessionStatus.IsVisible;
poseState.hmdPresenting = sessionStatus.HmdPresent;
poseState.hmdMounted = sessionStatus.HmdMounted;
poseState.displayLost = sessionStatus.DisplayLost;
poseState.shouldQuit = sessionStatus.ShouldQuit;
poseState.shouldRecenter = sessionStatus.ShouldRecenter;
sensorStates[eye].pose = poseState;
return sensorStates[eye];
}
kinc_vr_pose_state_t kinc_vr_interface_get_controller(int index) {
kinc_vr_pose_state_t todo;
return todo;
}
void kinc_vr_interface_warp_swap() {
// Initialize our single full screen Fov layer.
ovrLayerEyeFov ld = {};
ld.Header.Type = ovrLayerType_EyeFov;
ld.Header.Flags = 0;
if (isVisible) {
for (int eye = 0; eye < 2; ++eye) {
ld.ColorTexture[eye] = pEyeRenderTexture[eye]->TextureChain;
ld.Viewport[eye] = eyeRenderViewport[eye];
ld.Fov[eye] = hmdDesc.DefaultEyeFov[eye];
ld.RenderPose[eye] = EyeRenderPose[eye];
ld.SensorSampleTime = sensorSampleTime;
}
}
ovrLayerHeader *layers = &ld.Header;
ovrResult result = ovr_SubmitFrame(session, frameIndex, nullptr, &layers, 1);
if (!OVR_SUCCESS(result)) {
isVisible = false;
}
else {
isVisible = true;
}
frameIndex++;
// Render mirror
ID3D11Texture2D *tex = nullptr;
ovr_GetMirrorTextureBufferDX(session, mirrorTexture, IID_PPV_ARGS(&tex));
dx_ctx.context->CopyResource(backBuffer, tex);
tex->Release();
}
void kinc_vr_interface_update_tracking_origin(kinc_tracking_origin_t origin) {
switch (origin) {
case KINC_TRACKING_ORIGIN_STAND:
ovr_SetTrackingOriginType(session, ovrTrackingOrigin_FloorLevel);
break;
case KINC_TRACKING_ORIGIN_SIT:
ovr_SetTrackingOriginType(session, ovrTrackingOrigin_EyeLevel);
break;
default:
ovr_SetTrackingOriginType(session, ovrTrackingOrigin_FloorLevel);
break;
}
}
void kinc_vr_interface_reset_hmd_pose() {
ovr_RecenterTrackingOrigin(session);
}
void kinc_vr_interface_ovr_shutdown() {
ovr_Shutdown();
}
#endif

View File

@ -0,0 +1,384 @@
#include "graphics4/Direct3D11.h"
#include <kinc/graphics4/compute.h>
#include <kinc/graphics4/texture.h>
#include <kinc/log.h>
#include <kinc/math/core.h>
#include <kinc/backend/SystemMicrosoft.h>
#define NOMINMAX
#ifdef KORE_WINDOWSAPP
#include <d3d11_1.h>
#else
#pragma warning(disable : 4005)
#include <d3d11.h>
#endif
#include <assert.h>
static uint8_t constantsMemory[1024 * 4];
static int getMultipleOf16(int value) {
int ret = 16;
while (ret < value)
ret += 16;
return ret;
}
static void setInt(uint8_t *constants, uint32_t offset, uint32_t size, int value) {
if (size == 0)
return;
int *ints = (int *)&constants[offset];
ints[0] = value;
}
static void setFloat(uint8_t *constants, uint32_t offset, uint32_t size, float value) {
if (size == 0)
return;
float *floats = (float *)&constants[offset];
floats[0] = value;
}
static void setFloat2(uint8_t *constants, uint32_t offset, uint32_t size, float value1, float value2) {
if (size == 0)
return;
float *floats = (float *)&constants[offset];
floats[0] = value1;
floats[1] = value2;
}
static void setFloat3(uint8_t *constants, uint32_t offset, uint32_t size, float value1, float value2, float value3) {
if (size == 0)
return;
float *floats = (float *)&constants[offset];
floats[0] = value1;
floats[1] = value2;
floats[2] = value3;
}
static void setFloat4(uint8_t *constants, uint32_t offset, uint32_t size, float value1, float value2, float value3, float value4) {
if (size == 0)
return;
float *floats = (float *)&constants[offset];
floats[0] = value1;
floats[1] = value2;
floats[2] = value3;
floats[3] = value4;
}
static void setFloats(uint8_t *constants, uint32_t offset, uint32_t size, uint8_t columns, uint8_t rows, float *values, int count) {
if (size == 0)
return;
float *floats = (float *)&constants[offset];
if (columns == 4 && rows == 4) {
for (int i = 0; i < count / 16 && i < (int)size / 4; ++i) {
for (int y = 0; y < 4; ++y) {
for (int x = 0; x < 4; ++x) {
floats[i * 16 + x + y * 4] = values[i * 16 + y + x * 4];
}
}
}
}
else if (columns == 3 && rows == 3) {
for (int i = 0; i < count / 9 && i < (int)size / 3; ++i) {
for (int y = 0; y < 4; ++y) {
for (int x = 0; x < 4; ++x) {
floats[i * 12 + x + y * 4] = values[i * 9 + y + x * 3];
}
}
}
}
else if (columns == 2 && rows == 2) {
for (int i = 0; i < count / 4 && i < (int)size / 2; ++i) {
for (int y = 0; y < 4; ++y) {
for (int x = 0; x < 4; ++x) {
floats[i * 8 + x + y * 4] = values[i * 4 + y + x * 2];
}
}
}
}
else {
for (int i = 0; i < count && i * 4 < (int)size; ++i) {
floats[i] = values[i];
}
}
}
static void setBool(uint8_t *constants, uint32_t offset, uint32_t size, bool value) {
if (size == 0)
return;
int *ints = (int *)&constants[offset];
ints[0] = value ? 1 : 0;
}
static void setMatrix4(uint8_t *constants, uint32_t offset, uint32_t size, kinc_matrix4x4_t *value) {
if (size == 0)
return;
float *floats = (float *)&constants[offset];
for (int y = 0; y < 4; ++y) {
for (int x = 0; x < 4; ++x) {
floats[x + y * 4] = kinc_matrix4x4_get(value, y, x);
}
}
}
static void setMatrix3(uint8_t *constants, uint32_t offset, uint32_t size, kinc_matrix3x3_t *value) {
if (size == 0)
return;
float *floats = (float *)&constants[offset];
for (int y = 0; y < 3; ++y) {
for (int x = 0; x < 3; ++x) {
floats[x + y * 4] = kinc_matrix3x3_get(value, y, x);
}
}
}
void kinc_compute_shader_init(kinc_compute_shader_t *shader, void *_data, int length) {
unsigned index = 0;
uint8_t *data = (uint8_t *)_data;
#ifndef KINC_KONG
memset(&shader->impl.attributes, 0, sizeof(shader->impl.attributes));
int attributesCount = data[index++];
for (int i = 0; i < attributesCount; ++i) {
unsigned char name[256];
for (unsigned i2 = 0; i2 < 255; ++i2) {
name[i2] = data[index++];
if (name[i2] == 0)
break;
}
shader->impl.attributes[i].hash = kinc_internal_hash_name(name);
shader->impl.attributes[i].index = data[index++];
}
memset(&shader->impl.textures, 0, sizeof(shader->impl.textures));
uint8_t texCount = data[index++];
for (unsigned i = 0; i < texCount; ++i) {
unsigned char name[256];
for (unsigned i2 = 0; i2 < 255; ++i2) {
name[i2] = data[index++];
if (name[i2] == 0)
break;
}
shader->impl.textures[i].hash = kinc_internal_hash_name(name);
shader->impl.textures[i].index = data[index++];
}
memset(&shader->impl.constants, 0, sizeof(shader->impl.constants));
uint8_t constantCount = data[index++];
shader->impl.constantsSize = 0;
for (unsigned i = 0; i < constantCount; ++i) {
unsigned char name[256];
for (unsigned i2 = 0; i2 < 255; ++i2) {
name[i2] = data[index++];
if (name[i2] == 0)
break;
}
kinc_compute_internal_shader_constant_t constant;
constant.hash = kinc_internal_hash_name(name);
constant.offset = *(uint32_t *)&data[index];
index += 4;
constant.size = *(uint32_t *)&data[index];
index += 4;
constant.columns = data[index];
index += 1;
constant.rows = data[index];
index += 1;
shader->impl.constants[i] = constant;
shader->impl.constantsSize = constant.offset + constant.size;
}
#endif
shader->impl.length = (int)(length - index);
shader->impl.data = (uint8_t *)malloc(shader->impl.length);
assert(shader->impl.data != NULL);
memcpy(shader->impl.data, &data[index], shader->impl.length);
HRESULT hr =
dx_ctx.device->lpVtbl->CreateComputeShader(dx_ctx.device, shader->impl.data, shader->impl.length, NULL, (ID3D11ComputeShader **)&shader->impl.shader);
if (hr != S_OK) {
kinc_log(KINC_LOG_LEVEL_WARNING, "Could not initialize compute shader.");
return;
}
#ifndef KINC_KONG
D3D11_BUFFER_DESC desc;
desc.ByteWidth = getMultipleOf16(shader->impl.constantsSize);
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.CPUAccessFlags = 0;
desc.MiscFlags = 0;
desc.StructureByteStride = 0;
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateBuffer(dx_ctx.device, &desc, NULL, &shader->impl.constantBuffer));
#endif
}
void kinc_compute_shader_destroy(kinc_compute_shader_t *shader) {}
static kinc_compute_internal_shader_constant_t *findConstant(kinc_compute_internal_shader_constant_t *constants, uint32_t hash) {
for (int i = 0; i < 64; ++i) {
if (constants[i].hash == hash) {
return &constants[i];
}
}
return NULL;
}
static kinc_internal_hash_index_t *findTextureUnit(kinc_internal_hash_index_t *units, uint32_t hash) {
for (int i = 0; i < 64; ++i) {
if (units[i].hash == hash) {
return &units[i];
}
}
return NULL;
}
#ifndef KINC_KONG
kinc_compute_constant_location_t kinc_compute_shader_get_constant_location(kinc_compute_shader_t *shader, const char *name) {
kinc_compute_constant_location_t location;
uint32_t hash = kinc_internal_hash_name((unsigned char *)name);
kinc_compute_internal_shader_constant_t *constant = findConstant(shader->impl.constants, hash);
if (constant == NULL) {
location.impl.offset = 0;
location.impl.size = 0;
location.impl.columns = 0;
location.impl.rows = 0;
}
else {
location.impl.offset = constant->offset;
location.impl.size = constant->size;
location.impl.columns = constant->columns;
location.impl.rows = constant->rows;
}
if (location.impl.size == 0) {
kinc_log(KINC_LOG_LEVEL_WARNING, "Uniform %s not found.", name);
}
return location;
}
kinc_compute_texture_unit_t kinc_compute_shader_get_texture_unit(kinc_compute_shader_t *shader, const char *name) {
char unitName[64];
int unitOffset = 0;
size_t len = strlen(name);
if (len > 63)
len = 63;
strncpy(unitName, name, len + 1);
if (unitName[len - 1] == ']') { // Check for array - mySampler[2]
unitOffset = (int)(unitName[len - 2] - '0'); // Array index is unit offset
unitName[len - 3] = 0; // Strip array from name
}
uint32_t hash = kinc_internal_hash_name((unsigned char *)unitName);
kinc_compute_texture_unit_t unit;
kinc_internal_hash_index_t *vertexUnit = findTextureUnit(shader->impl.textures, hash);
if (vertexUnit == NULL) {
unit.impl.unit = -1;
#ifndef NDEBUG
static int notFoundCount = 0;
if (notFoundCount < 10) {
kinc_log(KINC_LOG_LEVEL_WARNING, "Sampler %s not found.", unitName);
++notFoundCount;
}
else if (notFoundCount == 10) {
kinc_log(KINC_LOG_LEVEL_WARNING, "Giving up on sampler not found messages.", unitName);
++notFoundCount;
}
#endif
}
else {
unit.impl.unit = vertexUnit->index + unitOffset;
}
return unit;
}
#endif
void kinc_compute_set_bool(kinc_compute_constant_location_t location, bool value) {
setBool(constantsMemory, location.impl.offset, location.impl.size, value);
}
void kinc_compute_set_int(kinc_compute_constant_location_t location, int value) {
setInt(constantsMemory, location.impl.offset, location.impl.size, value);
}
void kinc_compute_set_float(kinc_compute_constant_location_t location, float value) {
setFloat(constantsMemory, location.impl.offset, location.impl.size, value);
}
void kinc_compute_set_float2(kinc_compute_constant_location_t location, float value1, float value2) {
setFloat2(constantsMemory, location.impl.offset, location.impl.size, value1, value2);
}
void kinc_compute_set_float3(kinc_compute_constant_location_t location, float value1, float value2, float value3) {
setFloat3(constantsMemory, location.impl.offset, location.impl.size, value1, value2, value3);
}
void kinc_compute_set_float4(kinc_compute_constant_location_t location, float value1, float value2, float value3, float value4) {
setFloat4(constantsMemory, location.impl.offset, location.impl.size, value1, value2, value3, value4);
}
void kinc_compute_set_floats(kinc_compute_constant_location_t location, float *values, int count) {
setFloats(constantsMemory, location.impl.offset, location.impl.size, location.impl.columns, location.impl.rows, values, count);
}
void kinc_compute_set_matrix4(kinc_compute_constant_location_t location, kinc_matrix4x4_t *value) {
setMatrix4(constantsMemory, location.impl.offset, location.impl.size, value);
}
void kinc_compute_set_matrix3(kinc_compute_constant_location_t location, kinc_matrix3x3_t *value) {
setMatrix3(constantsMemory, location.impl.offset, location.impl.size, value);
}
void kinc_compute_set_texture(kinc_compute_texture_unit_t unit, struct kinc_g4_texture *texture, kinc_compute_access_t access) {
ID3D11ShaderResourceView *nullView = NULL;
dx_ctx.context->lpVtbl->PSSetShaderResources(dx_ctx.context, 0, 1, &nullView);
dx_ctx.context->lpVtbl->CSSetUnorderedAccessViews(dx_ctx.context, unit.impl.unit, 1, &texture->impl.computeView, NULL);
}
void kinc_compute_set_render_target(kinc_compute_texture_unit_t unit, struct kinc_g4_render_target *texture, kinc_compute_access_t access) {}
void kinc_compute_set_sampled_texture(kinc_compute_texture_unit_t unit, struct kinc_g4_texture *texture) {}
void kinc_compute_set_sampled_render_target(kinc_compute_texture_unit_t unit, struct kinc_g4_render_target *target) {}
void kinc_compute_set_sampled_depth_from_render_target(kinc_compute_texture_unit_t unit, struct kinc_g4_render_target *target) {}
void kinc_compute_set_texture_addressing(kinc_compute_texture_unit_t unit, kinc_g4_texture_direction_t dir, kinc_g4_texture_addressing_t addressing) {}
void kinc_compute_set_texture_magnification_filter(kinc_compute_texture_unit_t unit, kinc_g4_texture_filter_t filter) {}
void kinc_compute_set_texture_minification_filter(kinc_compute_texture_unit_t unit, kinc_g4_texture_filter_t filter) {}
void kinc_compute_set_texture_mipmap_filter(kinc_compute_texture_unit_t unit, kinc_g4_mipmap_filter_t filter) {}
void kinc_compute_set_texture3d_addressing(kinc_compute_texture_unit_t unit, kinc_g4_texture_direction_t dir, kinc_g4_texture_addressing_t addressing) {}
void kinc_compute_set_texture3d_magnification_filter(kinc_compute_texture_unit_t unit, kinc_g4_texture_filter_t filter) {}
void kinc_compute_set_texture3d_minification_filter(kinc_compute_texture_unit_t unit, kinc_g4_texture_filter_t filter) {}
void kinc_compute_set_texture3d_mipmap_filter(kinc_compute_texture_unit_t unit, kinc_g4_mipmap_filter_t filter) {}
void kinc_compute_set_shader(kinc_compute_shader_t *shader) {
dx_ctx.context->lpVtbl->CSSetShader(dx_ctx.context, (ID3D11ComputeShader *)shader->impl.shader, NULL, 0);
#ifndef KINC_KONG
dx_ctx.context->lpVtbl->UpdateSubresource(dx_ctx.context, (ID3D11Resource *)shader->impl.constantBuffer, 0, NULL, constantsMemory, 0, 0);
dx_ctx.context->lpVtbl->CSSetConstantBuffers(dx_ctx.context, 0, 1, &shader->impl.constantBuffer);
#endif
}
void kinc_compute(int x, int y, int z) {
dx_ctx.context->lpVtbl->Dispatch(dx_ctx.context, x, y, z);
ID3D11UnorderedAccessView *nullView = NULL;
dx_ctx.context->lpVtbl->CSSetUnorderedAccessViews(dx_ctx.context, 0, 1, &nullView, NULL);
}

View File

@ -0,0 +1,45 @@
#pragma once
#include <kinc/backend/graphics4/ShaderHash.h>
#ifdef __cplusplus
extern "C" {
#endif
struct ID3D11Buffer;
typedef struct {
uint32_t offset;
uint32_t size;
uint8_t columns;
uint8_t rows;
} kinc_compute_constant_location_impl_t;
typedef struct {
int unit;
} kinc_compute_texture_unit_impl_t;
typedef struct {
uint32_t hash;
uint32_t offset;
uint32_t size;
uint8_t columns;
uint8_t rows;
} kinc_compute_internal_shader_constant_t;
typedef struct {
#ifndef KINC_KONG
kinc_compute_internal_shader_constant_t constants[64];
int constantsSize;
kinc_internal_hash_index_t attributes[64];
kinc_internal_hash_index_t textures[64];
struct ID3D11Buffer *constantBuffer;
#endif
void *shader;
uint8_t *data;
int length;
} kinc_compute_shader_impl_t;
#ifdef __cplusplus
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,41 @@
#pragma once
#include <d3d11.h>
#include <dxgi.h>
#include <stdbool.h>
#define MAXIMUM_WINDOWS 16
struct dx_window {
HWND hwnd;
IDXGISwapChain *swapChain;
ID3D11Texture2D *backBuffer;
ID3D11RenderTargetView *renderTargetView;
ID3D11Texture2D *depthStencil;
ID3D11DepthStencilView *depthStencilView;
int width;
int height;
int new_width;
int new_height;
bool vsync;
int depth_bits;
int stencil_bits;
};
struct dx_context {
ID3D11Device *device;
ID3D11DeviceContext *context;
IDXGIDevice *dxgiDevice;
IDXGIAdapter *dxgiAdapter;
IDXGIFactory *dxgiFactory;
int current_window;
struct dx_window windows[MAXIMUM_WINDOWS];
};
extern struct dx_context dx_ctx;
#include <kinc/backend/SystemMicrosoft.h>

View File

@ -0,0 +1,11 @@
#include "ShaderHash.h"
// djb2
uint32_t kinc_internal_hash_name(unsigned char *str) {
unsigned long hash = 5381;
int c;
while (c = *str++) {
hash = hash * 33 ^ c;
}
return hash;
}

View File

@ -0,0 +1,19 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
uint32_t hash;
uint32_t index;
} kinc_internal_hash_index_t;
uint32_t kinc_internal_hash_name(unsigned char *str);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,51 @@
#ifdef KINC_KONG
#include <kinc/graphics4/constantbuffer.h>
void kinc_g4_constant_buffer_init(kinc_g4_constant_buffer *buffer, size_t size) {
buffer->impl.size = size;
buffer->impl.last_start = 0;
buffer->impl.last_size = size;
D3D11_BUFFER_DESC desc;
desc.ByteWidth = (UINT)get_multiple_of_16(size);
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
desc.Usage = D3D11_USAGE_DYNAMIC;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
desc.MiscFlags = 0;
desc.StructureByteStride = 0;
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateBuffer(dx_ctx.device, &desc, NULL, &buffer->impl.buffer));
}
void kinc_g4_constant_buffer_destroy(kinc_g4_constant_buffer *buffer) {
buffer->impl.buffer->lpVtbl->Release(buffer->impl.buffer);
}
uint8_t *kinc_g4_constant_buffer_lock_all(kinc_g4_constant_buffer *buffer) {
return kinc_g4_constant_buffer_lock(buffer, 0, kinc_g4_constant_buffer_size(buffer));
}
uint8_t *kinc_g4_constant_buffer_lock(kinc_g4_constant_buffer *buffer, size_t start, size_t size) {
buffer->impl.last_start = start;
buffer->impl.last_size = size;
D3D11_MAPPED_SUBRESOURCE mapped_resource;
memset(&mapped_resource, 0, sizeof(D3D11_MAPPED_SUBRESOURCE));
dx_ctx.context->lpVtbl->Map(dx_ctx.context, (ID3D11Resource *)buffer->impl.buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource);
uint8_t *data = (uint8_t *)mapped_resource.pData;
return &data[start];
}
void kinc_g4_constant_buffer_unlock_all(kinc_g4_constant_buffer *buffer) {
kinc_g4_constant_buffer_unlock(buffer, buffer->impl.last_size);
}
void kinc_g4_constant_buffer_unlock(kinc_g4_constant_buffer *buffer, size_t count) {
dx_ctx.context->lpVtbl->Unmap(dx_ctx.context, (ID3D11Resource *)buffer->impl.buffer, 0);
}
size_t kinc_g4_constant_buffer_size(kinc_g4_constant_buffer *buffer) {
return buffer->impl.size;
}
#endif

View File

@ -0,0 +1,14 @@
#pragma once
#ifdef KINC_KONG
struct ID3D11Buffer;
typedef struct kinc_g4_constant_buffer_impl {
struct ID3D11Buffer *buffer;
size_t size;
size_t last_start;
size_t last_size;
} kinc_g4_constant_buffer_impl;
#endif

View File

@ -0,0 +1,108 @@
// Windows 7
#define WINVER 0x0601
#define _WIN32_WINNT 0x0601
#define NOATOM
#define NOCLIPBOARD
#define NOCOLOR
#define NOCOMM
#define NOCTLMGR
#define NODEFERWINDOWPOS
#define NODRAWTEXT
#define NOGDI
#define NOGDICAPMASKS
#define NOHELP
#define NOICONS
#define NOKANJI
#define NOKEYSTATES
#define NOMB
#define NOMCX
#define NOMEMMGR
#define NOMENUS
#define NOMETAFILE
#define NOMINMAX
//#define NOMSG
#define NONLS
#define NOOPENFILE
#define NOPROFILER
#define NORASTEROPS
#define NOSCROLL
#define NOSERVICE
#define NOSHOWWINDOW
#define NOSOUND
#define NOSYSCOMMANDS
#define NOSYSMETRICS
#define NOTEXTMETRIC
//#define NOUSER
#define NOVIRTUALKEYCODES
#define NOWH
#define NOWINMESSAGES
#define NOWINOFFSETS
#define NOWINSTYLES
#define WIN32_LEAN_AND_MEAN
#include <kinc/graphics4/graphics.h>
#include <kinc/backend/SystemMicrosoft.h>
#ifdef KORE_WINDOWSAPP
#include <d3d11_1.h>
#else
#pragma warning(disable : 4005)
#include <d3d11.h>
#endif
#include "Direct3D11.h"
#include <assert.h>
#include <malloc.h>
#include <stdint.h>
struct dx_context dx_ctx = {0};
static uint8_t vertexConstants[1024 * 4];
static uint8_t fragmentConstants[1024 * 4];
static uint8_t geometryConstants[1024 * 4];
static uint8_t tessControlConstants[1024 * 4];
static uint8_t tessEvalConstants[1024 * 4];
static D3D11_COMPARISON_FUNC get_comparison(kinc_g4_compare_mode_t compare) {
switch (compare) {
default:
case KINC_G4_COMPARE_ALWAYS:
return D3D11_COMPARISON_ALWAYS;
case KINC_G4_COMPARE_NEVER:
return D3D11_COMPARISON_NEVER;
case KINC_G4_COMPARE_EQUAL:
return D3D11_COMPARISON_EQUAL;
case KINC_G4_COMPARE_NOT_EQUAL:
return D3D11_COMPARISON_NOT_EQUAL;
case KINC_G4_COMPARE_LESS:
return D3D11_COMPARISON_LESS;
case KINC_G4_COMPARE_LESS_EQUAL:
return D3D11_COMPARISON_LESS_EQUAL;
case KINC_G4_COMPARE_GREATER:
return D3D11_COMPARISON_GREATER;
case KINC_G4_COMPARE_GREATER_EQUAL:
return D3D11_COMPARISON_GREATER_EQUAL;
}
}
static size_t get_multiple_of_16(size_t value) {
size_t ret = 16;
while (ret < value) {
ret += 16;
}
return ret;
}
#include "Direct3D11.c.h"
#include "ShaderHash.c.h"
#include "constantbuffer.c.h"
#include "indexbuffer.c.h"
#include "pipeline.c.h"
#include "rendertarget.c.h"
#include "shader.c.h"
#include "texture.c.h"
#include "texturearray.c.h"
#include "vertexbuffer.c.h"

View File

@ -0,0 +1,89 @@
#include <kinc/graphics4/indexBuffer.h>
void kinc_g4_index_buffer_init(kinc_g4_index_buffer_t *buffer, int count, kinc_g4_index_buffer_format_t format, kinc_g4_usage_t usage) {
buffer->impl.count = count;
buffer->impl.sixteen = format == KINC_G4_INDEX_BUFFER_FORMAT_16BIT;
buffer->impl.last_start = 0;
buffer->impl.last_count = count;
uint32_t byte_size = buffer->impl.sixteen ? sizeof(uint16_t) * count : sizeof(uint32_t) * count;
if (usage == KINC_G4_USAGE_DYNAMIC) {
buffer->impl.indices = NULL;
}
else {
buffer->impl.indices = malloc(byte_size);
}
D3D11_BUFFER_DESC bufferDesc;
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
bufferDesc.ByteWidth = byte_size;
bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
bufferDesc.CPUAccessFlags = 0;
bufferDesc.MiscFlags = 0;
bufferDesc.StructureByteStride = 0;
buffer->impl.usage = usage;
switch (usage) {
case KINC_G4_USAGE_STATIC:
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
break;
case KINC_G4_USAGE_DYNAMIC:
bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
break;
case KINC_G4_USAGE_READABLE:
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
break;
}
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateBuffer(dx_ctx.device, &bufferDesc, NULL, &buffer->impl.ib));
}
void kinc_g4_index_buffer_destroy(kinc_g4_index_buffer_t *buffer) {
buffer->impl.ib->lpVtbl->Release(buffer->impl.ib);
free(buffer->impl.indices);
buffer->impl.indices = NULL;
}
static int kinc_g4_internal_index_buffer_stride(kinc_g4_index_buffer_t *buffer) {
return buffer->impl.sixteen ? 2 : 4;
}
void *kinc_g4_index_buffer_lock_all(kinc_g4_index_buffer_t *buffer) {
return kinc_g4_index_buffer_lock(buffer, 0, kinc_g4_index_buffer_count(buffer));
}
void *kinc_g4_index_buffer_lock(kinc_g4_index_buffer_t *buffer, int start, int count) {
buffer->impl.last_start = start;
buffer->impl.last_count = count;
if (buffer->impl.usage == KINC_G4_USAGE_DYNAMIC) {
D3D11_MAPPED_SUBRESOURCE mappedResource;
memset(&mappedResource, 0, sizeof(D3D11_MAPPED_SUBRESOURCE));
dx_ctx.context->lpVtbl->Map(dx_ctx.context, (ID3D11Resource *)buffer->impl.ib, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
uint8_t *data = (uint8_t *)mappedResource.pData;
return &data[start * kinc_g4_internal_index_buffer_stride(buffer)];
}
else {
uint8_t *data = (uint8_t *)buffer->impl.indices;
return &data[start * kinc_g4_internal_index_buffer_stride(buffer)];
}
}
void kinc_g4_index_buffer_unlock_all(kinc_g4_index_buffer_t *buffer) {
kinc_g4_index_buffer_unlock(buffer, buffer->impl.last_count);
}
void kinc_g4_index_buffer_unlock(kinc_g4_index_buffer_t *buffer, int count) {
if (buffer->impl.usage == KINC_G4_USAGE_DYNAMIC) {
dx_ctx.context->lpVtbl->Unmap(dx_ctx.context, (ID3D11Resource *)buffer->impl.ib, 0);
}
else {
dx_ctx.context->lpVtbl->UpdateSubresource(dx_ctx.context, (ID3D11Resource *)buffer->impl.ib, 0, NULL, buffer->impl.indices, 0, 0);
}
}
int kinc_g4_index_buffer_count(kinc_g4_index_buffer_t *buffer) {
return buffer->impl.count;
}

View File

@ -0,0 +1,13 @@
#pragma once
struct ID3D11Buffer;
typedef struct {
struct ID3D11Buffer *ib;
void *indices;
int count;
int usage;
bool sixteen;
int last_start;
int last_count;
} kinc_g4_index_buffer_impl_t;

View File

@ -0,0 +1,876 @@
#include <kinc/graphics4/pipeline.h>
#include <kinc/graphics4/shader.h>
#include <kinc/graphics4/vertexbuffer.h>
#include <kinc/libs/stb_sprintf.h>
#include <kinc/log.h>
kinc_g4_pipeline_t *currentPipeline = NULL;
float currentBlendFactor[4] = {0, 0, 0, 0};
bool needPipelineRebind = true;
static D3D11_CULL_MODE convert_cull_mode(kinc_g4_cull_mode_t cullMode) {
switch (cullMode) {
case KINC_G4_CULL_CLOCKWISE:
return D3D11_CULL_BACK;
case KINC_G4_CULL_COUNTER_CLOCKWISE:
return D3D11_CULL_FRONT;
case KINC_G4_CULL_NOTHING:
return D3D11_CULL_NONE;
default:
assert(false);
return D3D11_CULL_NONE;
}
}
static D3D11_BLEND convert_blend_factor(kinc_g4_blending_factor_t factor) {
switch (factor) {
case KINC_G4_BLEND_ONE:
return D3D11_BLEND_ONE;
case KINC_G4_BLEND_ZERO:
return D3D11_BLEND_ZERO;
case KINC_G4_BLEND_SOURCE_ALPHA:
return D3D11_BLEND_SRC_ALPHA;
case KINC_G4_BLEND_DEST_ALPHA:
return D3D11_BLEND_DEST_ALPHA;
case KINC_G4_BLEND_INV_SOURCE_ALPHA:
return D3D11_BLEND_INV_SRC_ALPHA;
case KINC_G4_BLEND_INV_DEST_ALPHA:
return D3D11_BLEND_INV_DEST_ALPHA;
case KINC_G4_BLEND_SOURCE_COLOR:
return D3D11_BLEND_SRC_COLOR;
case KINC_G4_BLEND_DEST_COLOR:
return D3D11_BLEND_DEST_COLOR;
case KINC_G4_BLEND_INV_SOURCE_COLOR:
return D3D11_BLEND_INV_SRC_COLOR;
case KINC_G4_BLEND_INV_DEST_COLOR:
return D3D11_BLEND_INV_DEST_COLOR;
default:
assert(false);
return D3D11_BLEND_SRC_ALPHA;
}
}
static D3D11_BLEND_OP convert_blend_operation(kinc_g4_blending_operation_t operation) {
switch (operation) {
case KINC_G4_BLENDOP_ADD:
return D3D11_BLEND_OP_ADD;
case KINC_G4_BLENDOP_SUBTRACT:
return D3D11_BLEND_OP_SUBTRACT;
case KINC_G4_BLENDOP_REVERSE_SUBTRACT:
return D3D11_BLEND_OP_REV_SUBTRACT;
case KINC_G4_BLENDOP_MIN:
return D3D11_BLEND_OP_MIN;
case KINC_G4_BLENDOP_MAX:
return D3D11_BLEND_OP_MAX;
default:
assert(false);
return D3D11_BLEND_OP_ADD;
}
}
static D3D11_STENCIL_OP get_stencil_action(kinc_g4_stencil_action_t action) {
switch (action) {
default:
case KINC_G4_STENCIL_KEEP:
return D3D11_STENCIL_OP_KEEP;
case KINC_G4_STENCIL_ZERO:
return D3D11_STENCIL_OP_ZERO;
case KINC_G4_STENCIL_REPLACE:
return D3D11_STENCIL_OP_REPLACE;
case KINC_G4_STENCIL_INCREMENT:
return D3D11_STENCIL_OP_INCR;
case KINC_G4_STENCIL_INCREMENT_WRAP:
return D3D11_STENCIL_OP_INCR_SAT;
case KINC_G4_STENCIL_DECREMENT:
return D3D11_STENCIL_OP_DECR;
case KINC_G4_STENCIL_DECREMENT_WRAP:
return D3D11_STENCIL_OP_DECR_SAT;
case KINC_G4_STENCIL_INVERT:
return D3D11_STENCIL_OP_INVERT;
}
}
void kinc_internal_set_constants(void) {
#ifndef KINC_KONG
if (currentPipeline->vertex_shader->impl.constantsSize > 0) {
dx_ctx.context->lpVtbl->UpdateSubresource(dx_ctx.context, (ID3D11Resource *)currentPipeline->impl.vertexConstantBuffer, 0, NULL, vertexConstants, 0, 0);
dx_ctx.context->lpVtbl->VSSetConstantBuffers(dx_ctx.context, 0, 1, &currentPipeline->impl.vertexConstantBuffer);
}
if (currentPipeline->fragment_shader->impl.constantsSize > 0) {
dx_ctx.context->lpVtbl->UpdateSubresource(dx_ctx.context, (ID3D11Resource *)currentPipeline->impl.fragmentConstantBuffer, 0, NULL, fragmentConstants, 0,
0);
dx_ctx.context->lpVtbl->PSSetConstantBuffers(dx_ctx.context, 0, 1, &currentPipeline->impl.fragmentConstantBuffer);
}
if (currentPipeline->geometry_shader != NULL && currentPipeline->geometry_shader->impl.constantsSize > 0) {
dx_ctx.context->lpVtbl->UpdateSubresource(dx_ctx.context, (ID3D11Resource *)currentPipeline->impl.geometryConstantBuffer, 0, NULL, geometryConstants, 0,
0);
dx_ctx.context->lpVtbl->GSSetConstantBuffers(dx_ctx.context, 0, 1, &currentPipeline->impl.geometryConstantBuffer);
}
if (currentPipeline->tessellation_control_shader != NULL && currentPipeline->tessellation_control_shader->impl.constantsSize > 0) {
dx_ctx.context->lpVtbl->UpdateSubresource(dx_ctx.context, (ID3D11Resource *)currentPipeline->impl.tessControlConstantBuffer, 0, NULL,
tessControlConstants, 0, 0);
dx_ctx.context->lpVtbl->HSSetConstantBuffers(dx_ctx.context, 0, 1, &currentPipeline->impl.tessControlConstantBuffer);
}
if (currentPipeline->tessellation_evaluation_shader != NULL && currentPipeline->tessellation_evaluation_shader->impl.constantsSize > 0) {
dx_ctx.context->lpVtbl->UpdateSubresource(dx_ctx.context, (ID3D11Resource *)currentPipeline->impl.tessEvalConstantBuffer, 0, NULL, tessEvalConstants, 0,
0);
dx_ctx.context->lpVtbl->DSSetConstantBuffers(dx_ctx.context, 0, 1, &currentPipeline->impl.tessEvalConstantBuffer);
}
#endif
}
void kinc_g4_pipeline_init(struct kinc_g4_pipeline *state) {
memset(state, 0, sizeof(struct kinc_g4_pipeline));
kinc_g4_internal_pipeline_set_defaults(state);
state->impl.d3d11inputLayout = NULL;
state->impl.fragmentConstantBuffer = NULL;
state->impl.vertexConstantBuffer = NULL;
state->impl.geometryConstantBuffer = NULL;
state->impl.tessEvalConstantBuffer = NULL;
state->impl.tessControlConstantBuffer = NULL;
state->impl.depthStencilState = NULL;
state->impl.rasterizerState = NULL;
state->impl.rasterizerStateScissor = NULL;
state->impl.blendState = NULL;
}
void kinc_g4_pipeline_destroy(struct kinc_g4_pipeline *state) {
if (state->impl.d3d11inputLayout != NULL) {
state->impl.d3d11inputLayout->lpVtbl->Release(state->impl.d3d11inputLayout);
state->impl.d3d11inputLayout = NULL;
}
if (state->impl.fragmentConstantBuffer != NULL) {
state->impl.fragmentConstantBuffer->lpVtbl->Release(state->impl.fragmentConstantBuffer);
state->impl.fragmentConstantBuffer = NULL;
}
if (state->impl.vertexConstantBuffer != NULL) {
state->impl.vertexConstantBuffer->lpVtbl->Release(state->impl.vertexConstantBuffer);
state->impl.vertexConstantBuffer = NULL;
}
if (state->impl.geometryConstantBuffer != NULL) {
state->impl.geometryConstantBuffer->lpVtbl->Release(state->impl.geometryConstantBuffer);
state->impl.geometryConstantBuffer = NULL;
}
if (state->impl.tessEvalConstantBuffer != NULL) {
state->impl.tessEvalConstantBuffer->lpVtbl->Release(state->impl.tessEvalConstantBuffer);
state->impl.tessEvalConstantBuffer = NULL;
}
if (state->impl.tessControlConstantBuffer != NULL) {
state->impl.tessControlConstantBuffer->lpVtbl->Release(state->impl.tessControlConstantBuffer);
state->impl.tessControlConstantBuffer = NULL;
}
if (state->impl.depthStencilState != NULL) {
state->impl.depthStencilState->lpVtbl->Release(state->impl.depthStencilState);
state->impl.depthStencilState = NULL;
}
if (state->impl.rasterizerState != NULL) {
state->impl.rasterizerState->lpVtbl->Release(state->impl.rasterizerState);
state->impl.rasterizerState = NULL;
}
if (state->impl.rasterizerStateScissor != NULL) {
state->impl.rasterizerStateScissor->lpVtbl->Release(state->impl.rasterizerStateScissor);
state->impl.rasterizerStateScissor = NULL;
}
if (state->impl.blendState != NULL) {
state->impl.blendState->lpVtbl->Release(state->impl.blendState);
state->impl.blendState = NULL;
}
}
void kinc_internal_set_rasterizer_state(struct kinc_g4_pipeline *pipeline, bool scissoring) {
if (scissoring && pipeline->impl.rasterizerStateScissor != NULL)
dx_ctx.context->lpVtbl->RSSetState(dx_ctx.context, pipeline->impl.rasterizerStateScissor);
else if (pipeline->impl.rasterizerState != NULL)
dx_ctx.context->lpVtbl->RSSetState(dx_ctx.context, pipeline->impl.rasterizerState);
}
void kinc_internal_set_pipeline(struct kinc_g4_pipeline *pipeline, bool scissoring) {
dx_ctx.context->lpVtbl->OMSetDepthStencilState(dx_ctx.context, pipeline->impl.depthStencilState, pipeline->stencil_reference_value);
UINT sampleMask = 0xffffffff;
dx_ctx.context->lpVtbl->OMSetBlendState(dx_ctx.context, pipeline->impl.blendState, currentBlendFactor, sampleMask);
kinc_internal_set_rasterizer_state(pipeline, scissoring);
dx_ctx.context->lpVtbl->VSSetShader(dx_ctx.context, (ID3D11VertexShader *)pipeline->vertex_shader->impl.shader, NULL, 0);
dx_ctx.context->lpVtbl->PSSetShader(dx_ctx.context, (ID3D11PixelShader *)pipeline->fragment_shader->impl.shader, NULL, 0);
dx_ctx.context->lpVtbl->GSSetShader(dx_ctx.context,
pipeline->geometry_shader != NULL ? (ID3D11GeometryShader *)pipeline->geometry_shader->impl.shader : NULL, NULL, 0);
dx_ctx.context->lpVtbl->HSSetShader(
dx_ctx.context, pipeline->tessellation_control_shader != NULL ? (ID3D11HullShader *)pipeline->tessellation_control_shader->impl.shader : NULL, NULL, 0);
dx_ctx.context->lpVtbl->DSSetShader(
dx_ctx.context, pipeline->tessellation_evaluation_shader != NULL ? (ID3D11DomainShader *)pipeline->tessellation_evaluation_shader->impl.shader : NULL,
NULL, 0);
dx_ctx.context->lpVtbl->IASetInputLayout(dx_ctx.context, pipeline->impl.d3d11inputLayout);
}
void kinc_internal_pipeline_rebind() {
if (currentPipeline != NULL && needPipelineRebind) {
kinc_internal_set_pipeline(currentPipeline, kinc_internal_scissoring);
needPipelineRebind = false;
}
}
#ifndef KINC_KONG
static kinc_internal_shader_constant_t *findConstant(kinc_internal_shader_constant_t *constants, uint32_t hash) {
for (int i = 0; i < 64; ++i) {
if (constants[i].hash == hash) {
return &constants[i];
}
}
return NULL;
}
static kinc_internal_hash_index_t *findTextureUnit(kinc_internal_hash_index_t *units, uint32_t hash) {
for (int i = 0; i < 64; ++i) {
if (units[i].hash == hash) {
return &units[i];
}
}
return NULL;
}
void kinc_g4_pipeline_get_constant_locations(kinc_g4_pipeline_t *state, kinc_g4_constant_location_t *vertex_locations,
kinc_g4_constant_location_t *fragment_locations, int *vertex_sizes, int *fragment_sizes, int *max_vertex,
int *max_fragment) {
// *max_vertex = state->vertex_shader->impl.constantsSize;
// *max_fragment = state->fragment_shader->impl.constantsSize;
// if (vertex_locations != null && fragment_locations != null) {
// for (int i = 0; i < state->vertex_shader->impl.constantsSize; i++) {
// kinc_internal_shader_constant_t *constant = state->vertex_shader->impl.constants[i];
// vertex_location[i].impl.vertexOffset = constant->offset;
// vertex_location[i].impl.vertexSize = constant->size;
// vertex_location[i].impl.vertexColumns = constant->columns;
// vertex_location[i].impl.vertexRows = constant->rows;
// vertex_sizes[i] = constant->size;
// }
// for (int i = 0; i < state->fragment_shader->impl.constantsSize; i++) {
// kinc_internal_shader_constant_t *constant = state->fragment_shader->impl.constants[i];
// fragment_location[i].impl.vertexOffset = constant->offset;
// fragment_location[i].impl.vertexSize = constant->size;
// fragment_location[i].impl.vertexColumns = constant->columns;
// fragment_location[i].impl.vertexRows = constant->rows;
// fragment_sizes[i] = constant->size;
// }
// }
}
kinc_g4_constant_location_t kinc_g4_pipeline_get_constant_location(struct kinc_g4_pipeline *state, const char *name) {
kinc_g4_constant_location_t location;
uint32_t hash = kinc_internal_hash_name((unsigned char *)name);
kinc_internal_shader_constant_t *constant = findConstant(state->vertex_shader->impl.constants, hash);
if (constant == NULL) {
location.impl.vertexOffset = 0;
location.impl.vertexSize = 0;
location.impl.vertexColumns = 0;
location.impl.vertexRows = 0;
}
else {
location.impl.vertexOffset = constant->offset;
location.impl.vertexSize = constant->size;
location.impl.vertexColumns = constant->columns;
location.impl.vertexRows = constant->rows;
}
constant = findConstant(state->fragment_shader->impl.constants, hash);
if (constant == NULL) {
location.impl.fragmentOffset = 0;
location.impl.fragmentSize = 0;
location.impl.fragmentColumns = 0;
location.impl.fragmentRows = 0;
}
else {
location.impl.fragmentOffset = constant->offset;
location.impl.fragmentSize = constant->size;
location.impl.fragmentColumns = constant->columns;
location.impl.fragmentRows = constant->rows;
}
constant = state->geometry_shader == NULL ? NULL : findConstant(state->geometry_shader->impl.constants, hash);
if (constant == NULL) {
location.impl.geometryOffset = 0;
location.impl.geometrySize = 0;
location.impl.geometryColumns = 0;
location.impl.geometryRows = 0;
}
else {
location.impl.geometryOffset = constant->offset;
location.impl.geometrySize = constant->size;
location.impl.geometryColumns = constant->columns;
location.impl.geometryRows = constant->rows;
}
constant = state->tessellation_control_shader == NULL ? NULL : findConstant(state->tessellation_control_shader->impl.constants, hash);
if (constant == NULL) {
location.impl.tessControlOffset = 0;
location.impl.tessControlSize = 0;
location.impl.tessControlColumns = 0;
location.impl.tessControlRows = 0;
}
else {
location.impl.tessControlOffset = constant->offset;
location.impl.tessControlSize = constant->size;
location.impl.tessControlColumns = constant->columns;
location.impl.tessControlRows = constant->rows;
}
constant = state->tessellation_evaluation_shader == NULL ? NULL : findConstant(state->tessellation_evaluation_shader->impl.constants, hash);
if (constant == NULL) {
location.impl.tessEvalOffset = 0;
location.impl.tessEvalSize = 0;
location.impl.tessEvalColumns = 0;
location.impl.tessEvalRows = 0;
}
else {
location.impl.tessEvalOffset = constant->offset;
location.impl.tessEvalSize = constant->size;
location.impl.tessEvalColumns = constant->columns;
location.impl.tessEvalRows = constant->rows;
}
if (location.impl.vertexSize == 0 && location.impl.fragmentSize == 0 && location.impl.geometrySize == 0 && location.impl.tessControlSize == 0 &&
location.impl.tessEvalSize == 0) {
kinc_log(KINC_LOG_LEVEL_WARNING, "Uniform %s not found.", name);
}
return location;
}
kinc_g4_texture_unit_t kinc_g4_pipeline_get_texture_unit(struct kinc_g4_pipeline *state, const char *name) {
char unitName[64];
int unitOffset = 0;
size_t len = strlen(name);
if (len > 63)
len = 63;
strncpy(unitName, name, len + 1);
if (unitName[len - 1] == ']') { // Check for array - mySampler[2]
unitOffset = (int)(unitName[len - 2] - '0'); // Array index is unit offset
unitName[len - 3] = 0; // Strip array from name
}
uint32_t hash = kinc_internal_hash_name((unsigned char *)unitName);
kinc_g4_texture_unit_t unit;
for (int i = 0; i < KINC_G4_SHADER_TYPE_COUNT; ++i) {
unit.stages[i] = -1;
}
kinc_internal_hash_index_t *fragmentUnit = findTextureUnit(state->fragment_shader->impl.textures, hash);
if (fragmentUnit != NULL) {
unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] = fragmentUnit->index + unitOffset;
}
kinc_internal_hash_index_t *vertexUnit = findTextureUnit(state->vertex_shader->impl.textures, hash);
if (vertexUnit != NULL) {
unit.stages[KINC_G4_SHADER_TYPE_VERTEX] = vertexUnit->index + unitOffset;
}
return unit;
}
#endif
static char stringCache[1024];
static int stringCacheIndex = 0;
static void setVertexDesc(D3D11_INPUT_ELEMENT_DESC *vertexDesc, int attributeIndex, int index, int stream, bool instanced, int subindex) {
if (subindex < 0) {
vertexDesc->SemanticName = "TEXCOORD";
vertexDesc->SemanticIndex = attributeIndex;
}
else {
// SPIRV_CROSS uses TEXCOORD_0_0,... for split up matrices
int stringStart = stringCacheIndex;
strcpy(&stringCache[stringCacheIndex], "TEXCOORD");
stringCacheIndex += (int)strlen("TEXCOORD");
sprintf(&stringCache[stringCacheIndex], "%i", attributeIndex);
stringCacheIndex += (int)strlen(&stringCache[stringCacheIndex]);
strcpy(&stringCache[stringCacheIndex], "_");
stringCacheIndex += 2;
vertexDesc->SemanticName = &stringCache[stringStart];
vertexDesc->SemanticIndex = subindex;
}
vertexDesc->InputSlot = stream;
vertexDesc->AlignedByteOffset = (index == 0) ? 0 : D3D11_APPEND_ALIGNED_ELEMENT;
vertexDesc->InputSlotClass = instanced ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA;
vertexDesc->InstanceDataStepRate = instanced ? 1 : 0;
}
#define usedCount 32
static int getAttributeLocation(kinc_internal_hash_index_t *attributes, const char *name, bool *used) {
uint32_t hash = kinc_internal_hash_name((unsigned char *)name);
for (int i = 0; i < 64; ++i) {
if (attributes[i].hash == hash) {
return attributes[i].index;
}
}
for (int i = 0; i < usedCount; ++i) {
if (!used[i]) {
used[i] = true;
return i;
}
}
return 0;
}
static void createRenderTargetBlendDesc(struct kinc_g4_pipeline *pipe, D3D11_RENDER_TARGET_BLEND_DESC *rtbd, int targetNum) {
rtbd->BlendEnable = pipe->blend_source != KINC_G4_BLEND_ONE || pipe->blend_destination != KINC_G4_BLEND_ZERO ||
pipe->alpha_blend_source != KINC_G4_BLEND_ONE || pipe->alpha_blend_destination != KINC_G4_BLEND_ZERO;
rtbd->SrcBlend = convert_blend_factor(pipe->blend_source);
rtbd->DestBlend = convert_blend_factor(pipe->blend_destination);
rtbd->BlendOp = convert_blend_operation(pipe->blend_operation);
rtbd->SrcBlendAlpha = convert_blend_factor(pipe->alpha_blend_source);
rtbd->DestBlendAlpha = convert_blend_factor(pipe->alpha_blend_destination);
rtbd->BlendOpAlpha = convert_blend_operation(pipe->alpha_blend_operation);
rtbd->RenderTargetWriteMask = (((pipe->color_write_mask_red[targetNum] ? D3D11_COLOR_WRITE_ENABLE_RED : 0) |
(pipe->color_write_mask_green[targetNum] ? D3D11_COLOR_WRITE_ENABLE_GREEN : 0)) |
(pipe->color_write_mask_blue[targetNum] ? D3D11_COLOR_WRITE_ENABLE_BLUE : 0)) |
(pipe->color_write_mask_alpha[targetNum] ? D3D11_COLOR_WRITE_ENABLE_ALPHA : 0);
}
void kinc_g4_pipeline_compile(struct kinc_g4_pipeline *state) {
#ifndef KINC_KONG
if (state->vertex_shader->impl.constantsSize > 0) {
D3D11_BUFFER_DESC desc;
desc.ByteWidth = (UINT)get_multiple_of_16(state->vertex_shader->impl.constantsSize);
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.CPUAccessFlags = 0;
desc.MiscFlags = 0;
desc.StructureByteStride = 0;
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateBuffer(dx_ctx.device, &desc, NULL, &state->impl.vertexConstantBuffer));
}
if (state->fragment_shader->impl.constantsSize > 0) {
D3D11_BUFFER_DESC desc;
desc.ByteWidth = (UINT)get_multiple_of_16(state->fragment_shader->impl.constantsSize);
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.CPUAccessFlags = 0;
desc.MiscFlags = 0;
desc.StructureByteStride = 0;
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateBuffer(dx_ctx.device, &desc, NULL, &state->impl.fragmentConstantBuffer));
}
if (state->geometry_shader != NULL && state->geometry_shader->impl.constantsSize > 0) {
D3D11_BUFFER_DESC desc;
desc.ByteWidth = (UINT)get_multiple_of_16(state->geometry_shader->impl.constantsSize);
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.CPUAccessFlags = 0;
desc.MiscFlags = 0;
desc.StructureByteStride = 0;
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateBuffer(dx_ctx.device, &desc, NULL, &state->impl.geometryConstantBuffer));
}
if (state->tessellation_control_shader != NULL && state->tessellation_control_shader->impl.constantsSize > 0) {
D3D11_BUFFER_DESC desc;
desc.ByteWidth = (UINT)get_multiple_of_16(state->tessellation_control_shader->impl.constantsSize);
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.CPUAccessFlags = 0;
desc.MiscFlags = 0;
desc.StructureByteStride = 0;
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateBuffer(dx_ctx.device, &desc, NULL, &state->impl.tessControlConstantBuffer));
}
if (state->tessellation_evaluation_shader != NULL && state->tessellation_evaluation_shader->impl.constantsSize > 0) {
D3D11_BUFFER_DESC desc;
desc.ByteWidth = (UINT)get_multiple_of_16(state->tessellation_evaluation_shader->impl.constantsSize);
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.CPUAccessFlags = 0;
desc.MiscFlags = 0;
desc.StructureByteStride = 0;
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateBuffer(dx_ctx.device, &desc, NULL, &state->impl.tessEvalConstantBuffer));
}
#endif
int all = 0;
for (int stream = 0; state->input_layout[stream] != NULL; ++stream) {
for (int index = 0; index < state->input_layout[stream]->size; ++index) {
if (state->input_layout[stream]->elements[index].data == KINC_G4_VERTEX_DATA_F32_4X4) {
all += 4;
}
else {
all += 1;
}
}
}
#ifndef KINC_KONG
bool used[usedCount];
for (int i = 0; i < usedCount; ++i)
used[i] = false;
for (int i = 0; i < 64; ++i) {
used[state->vertex_shader->impl.attributes[i].index] = true;
}
#endif
stringCacheIndex = 0;
D3D11_INPUT_ELEMENT_DESC *vertexDesc = (D3D11_INPUT_ELEMENT_DESC *)alloca(sizeof(D3D11_INPUT_ELEMENT_DESC) * all);
#ifdef KINC_KONG
#define getAttributeLocation(a, b, c) index
#endif
int i = 0;
for (int stream = 0; state->input_layout[stream] != NULL; ++stream) {
for (int index = 0; index < state->input_layout[stream]->size; ++index) {
switch (state->input_layout[stream]->elements[index].data) {
case KINC_G4_VERTEX_DATA_F32_1X:
setVertexDesc(&vertexDesc[i],
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
stream, state->input_layout[stream]->instanced, -1);
vertexDesc[i].Format = DXGI_FORMAT_R32_FLOAT;
++i;
break;
case KINC_G4_VERTEX_DATA_F32_2X:
setVertexDesc(&vertexDesc[i],
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
stream, state->input_layout[stream]->instanced, -1);
vertexDesc[i].Format = DXGI_FORMAT_R32G32_FLOAT;
++i;
break;
case KINC_G4_VERTEX_DATA_F32_3X:
setVertexDesc(&vertexDesc[i],
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
stream, state->input_layout[stream]->instanced, -1);
vertexDesc[i].Format = DXGI_FORMAT_R32G32B32_FLOAT;
++i;
break;
case KINC_G4_VERTEX_DATA_F32_4X:
setVertexDesc(&vertexDesc[i],
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
stream, state->input_layout[stream]->instanced, -1);
vertexDesc[i].Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
++i;
break;
case KINC_G4_VERTEX_DATA_I8_1X:
setVertexDesc(&vertexDesc[i],
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
stream, state->input_layout[stream]->instanced, -1);
vertexDesc[i].Format = DXGI_FORMAT_R8_SINT;
++i;
break;
case KINC_G4_VERTEX_DATA_U8_1X:
setVertexDesc(&vertexDesc[i],
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
stream, state->input_layout[stream]->instanced, -1);
vertexDesc[i].Format = DXGI_FORMAT_R8_UINT;
++i;
break;
case KINC_G4_VERTEX_DATA_I8_1X_NORMALIZED:
setVertexDesc(&vertexDesc[i],
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
stream, state->input_layout[stream]->instanced, -1);
vertexDesc[i].Format = DXGI_FORMAT_R8_SNORM;
++i;
break;
case KINC_G4_VERTEX_DATA_U8_1X_NORMALIZED:
setVertexDesc(&vertexDesc[i],
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
stream, state->input_layout[stream]->instanced, -1);
vertexDesc[i].Format = DXGI_FORMAT_R8_UNORM;
++i;
break;
case KINC_G4_VERTEX_DATA_I8_2X:
setVertexDesc(&vertexDesc[i],
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
stream, state->input_layout[stream]->instanced, -1);
vertexDesc[i].Format = DXGI_FORMAT_R8G8_SINT;
++i;
break;
case KINC_G4_VERTEX_DATA_U8_2X:
setVertexDesc(&vertexDesc[i],
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
stream, state->input_layout[stream]->instanced, -1);
vertexDesc[i].Format = DXGI_FORMAT_R8G8_UINT;
++i;
break;
case KINC_G4_VERTEX_DATA_I8_2X_NORMALIZED:
setVertexDesc(&vertexDesc[i],
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
stream, state->input_layout[stream]->instanced, -1);
vertexDesc[i].Format = DXGI_FORMAT_R8G8_SNORM;
++i;
break;
case KINC_G4_VERTEX_DATA_U8_2X_NORMALIZED:
setVertexDesc(&vertexDesc[i],
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
stream, state->input_layout[stream]->instanced, -1);
vertexDesc[i].Format = DXGI_FORMAT_R8G8_UNORM;
++i;
break;
case KINC_G4_VERTEX_DATA_I8_4X:
setVertexDesc(&vertexDesc[i],
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
stream, state->input_layout[stream]->instanced, -1);
vertexDesc[i].Format = DXGI_FORMAT_R8G8B8A8_SINT;
++i;
break;
case KINC_G4_VERTEX_DATA_U8_4X:
setVertexDesc(&vertexDesc[i],
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
stream, state->input_layout[stream]->instanced, -1);
vertexDesc[i].Format = DXGI_FORMAT_R8G8B8A8_UINT;
++i;
break;
case KINC_G4_VERTEX_DATA_I8_4X_NORMALIZED:
setVertexDesc(&vertexDesc[i],
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
stream, state->input_layout[stream]->instanced, -1);
vertexDesc[i].Format = DXGI_FORMAT_R8G8B8A8_SNORM;
++i;
break;
case KINC_G4_VERTEX_DATA_U8_4X_NORMALIZED:
setVertexDesc(&vertexDesc[i],
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
stream, state->input_layout[stream]->instanced, -1);
vertexDesc[i].Format = DXGI_FORMAT_R8G8B8A8_UNORM;
++i;
break;
case KINC_G4_VERTEX_DATA_I16_1X:
setVertexDesc(&vertexDesc[i],
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
stream, state->input_layout[stream]->instanced, -1);
vertexDesc[i].Format = DXGI_FORMAT_R16_SINT;
++i;
break;
case KINC_G4_VERTEX_DATA_U16_1X:
setVertexDesc(&vertexDesc[i],
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
stream, state->input_layout[stream]->instanced, -1);
vertexDesc[i].Format = DXGI_FORMAT_R16_UINT;
++i;
break;
case KINC_G4_VERTEX_DATA_I16_1X_NORMALIZED:
setVertexDesc(&vertexDesc[i],
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
stream, state->input_layout[stream]->instanced, -1);
vertexDesc[i].Format = DXGI_FORMAT_R16_SNORM;
++i;
break;
case KINC_G4_VERTEX_DATA_U16_1X_NORMALIZED:
setVertexDesc(&vertexDesc[i],
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
stream, state->input_layout[stream]->instanced, -1);
vertexDesc[i].Format = DXGI_FORMAT_R16_UNORM;
++i;
break;
case KINC_G4_VERTEX_DATA_I16_2X:
setVertexDesc(&vertexDesc[i],
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
stream, state->input_layout[stream]->instanced, -1);
vertexDesc[i].Format = DXGI_FORMAT_R16G16_SINT;
++i;
break;
case KINC_G4_VERTEX_DATA_U16_2X:
setVertexDesc(&vertexDesc[i],
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
stream, state->input_layout[stream]->instanced, -1);
vertexDesc[i].Format = DXGI_FORMAT_R16G16_UINT;
++i;
break;
case KINC_G4_VERTEX_DATA_I16_2X_NORMALIZED:
setVertexDesc(&vertexDesc[i],
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
stream, state->input_layout[stream]->instanced, -1);
vertexDesc[i].Format = DXGI_FORMAT_R16G16_SNORM;
++i;
break;
case KINC_G4_VERTEX_DATA_U16_2X_NORMALIZED:
setVertexDesc(&vertexDesc[i],
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
stream, state->input_layout[stream]->instanced, -1);
vertexDesc[i].Format = DXGI_FORMAT_R16G16_UNORM;
++i;
break;
case KINC_G4_VERTEX_DATA_I16_4X:
setVertexDesc(&vertexDesc[i],
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
stream, state->input_layout[stream]->instanced, -1);
vertexDesc[i].Format = DXGI_FORMAT_R16G16B16A16_SINT;
++i;
break;
case KINC_G4_VERTEX_DATA_U16_4X:
setVertexDesc(&vertexDesc[i],
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
stream, state->input_layout[stream]->instanced, -1);
vertexDesc[i].Format = DXGI_FORMAT_R16G16B16A16_UINT;
++i;
break;
case KINC_G4_VERTEX_DATA_I16_4X_NORMALIZED:
setVertexDesc(&vertexDesc[i],
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
stream, state->input_layout[stream]->instanced, -1);
vertexDesc[i].Format = DXGI_FORMAT_R16G16B16A16_SNORM;
++i;
break;
case KINC_G4_VERTEX_DATA_U16_4X_NORMALIZED:
setVertexDesc(&vertexDesc[i],
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
stream, state->input_layout[stream]->instanced, -1);
vertexDesc[i].Format = DXGI_FORMAT_R16G16B16A16_UNORM;
++i;
break;
case KINC_G4_VERTEX_DATA_I32_1X:
setVertexDesc(&vertexDesc[i],
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
stream, state->input_layout[stream]->instanced, -1);
vertexDesc[i].Format = DXGI_FORMAT_R32_SINT;
++i;
break;
case KINC_G4_VERTEX_DATA_U32_1X:
setVertexDesc(&vertexDesc[i],
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
stream, state->input_layout[stream]->instanced, -1);
vertexDesc[i].Format = DXGI_FORMAT_R32_UINT;
++i;
break;
case KINC_G4_VERTEX_DATA_I32_2X:
setVertexDesc(&vertexDesc[i],
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
stream, state->input_layout[stream]->instanced, -1);
vertexDesc[i].Format = DXGI_FORMAT_R32G32_SINT;
++i;
break;
case KINC_G4_VERTEX_DATA_U32_2X:
setVertexDesc(&vertexDesc[i],
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
stream, state->input_layout[stream]->instanced, -1);
vertexDesc[i].Format = DXGI_FORMAT_R32G32_UINT;
++i;
break;
case KINC_G4_VERTEX_DATA_I32_3X:
setVertexDesc(&vertexDesc[i],
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
stream, state->input_layout[stream]->instanced, -1);
vertexDesc[i].Format = DXGI_FORMAT_R32G32B32_SINT;
++i;
break;
case KINC_G4_VERTEX_DATA_U32_3X:
setVertexDesc(&vertexDesc[i],
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
stream, state->input_layout[stream]->instanced, -1);
vertexDesc[i].Format = DXGI_FORMAT_R32G32B32_UINT;
++i;
break;
case KINC_G4_VERTEX_DATA_I32_4X:
setVertexDesc(&vertexDesc[i],
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
stream, state->input_layout[stream]->instanced, -1);
vertexDesc[i].Format = DXGI_FORMAT_R32G32B32A32_SINT;
++i;
break;
case KINC_G4_VERTEX_DATA_U32_4X:
setVertexDesc(&vertexDesc[i],
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
stream, state->input_layout[stream]->instanced, -1);
vertexDesc[i].Format = DXGI_FORMAT_R32G32B32A32_UINT;
++i;
break;
case KINC_G4_VERTEX_DATA_F32_4X4: {
char name[101];
strcpy(name, state->input_layout[stream]->elements[index].name);
strcat(name, "_");
size_t length = strlen(name);
sprintf(&name[length], "%i", 0);
name[length + 1] = 0;
int attributeLocation = getAttributeLocation(state->vertex_shader->impl.attributes, name, used);
for (int i2 = 0; i2 < 4; ++i2) {
setVertexDesc(&vertexDesc[i], attributeLocation, index + i2, stream, state->input_layout[stream]->instanced, i2);
vertexDesc[i].Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
++i;
}
break;
}
}
}
}
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateInputLayout(dx_ctx.device, vertexDesc, all, state->vertex_shader->impl.data,
state->vertex_shader->impl.length, &state->impl.d3d11inputLayout));
{
D3D11_DEPTH_STENCIL_DESC desc;
memset(&desc, 0, sizeof(desc));
desc.DepthEnable = state->depth_mode != KINC_G4_COMPARE_ALWAYS;
desc.DepthWriteMask = state->depth_write ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
desc.DepthFunc = get_comparison(state->depth_mode);
desc.StencilEnable = state->stencil_front_mode != KINC_G4_COMPARE_ALWAYS || state->stencil_back_mode != KINC_G4_COMPARE_ALWAYS ||
state->stencil_front_both_pass != KINC_G4_STENCIL_KEEP || state->stencil_back_both_pass != KINC_G4_STENCIL_KEEP ||
state->stencil_front_depth_fail != KINC_G4_STENCIL_KEEP || state->stencil_back_depth_fail != KINC_G4_STENCIL_KEEP ||
state->stencil_front_fail != KINC_G4_STENCIL_KEEP || state->stencil_back_fail != KINC_G4_STENCIL_KEEP;
desc.StencilReadMask = state->stencil_read_mask;
desc.StencilWriteMask = state->stencil_write_mask;
desc.FrontFace.StencilFunc = desc.BackFace.StencilFunc = get_comparison(state->stencil_front_mode);
desc.FrontFace.StencilDepthFailOp = desc.BackFace.StencilDepthFailOp = get_stencil_action(state->stencil_front_depth_fail);
desc.FrontFace.StencilPassOp = desc.BackFace.StencilPassOp = get_stencil_action(state->stencil_front_both_pass);
desc.FrontFace.StencilFailOp = desc.BackFace.StencilFailOp = get_stencil_action(state->stencil_front_fail);
desc.BackFace.StencilFunc = desc.BackFace.StencilFunc = get_comparison(state->stencil_back_mode);
desc.BackFace.StencilDepthFailOp = desc.BackFace.StencilDepthFailOp = get_stencil_action(state->stencil_back_depth_fail);
desc.BackFace.StencilPassOp = desc.BackFace.StencilPassOp = get_stencil_action(state->stencil_back_both_pass);
desc.BackFace.StencilFailOp = desc.BackFace.StencilFailOp = get_stencil_action(state->stencil_back_fail);
dx_ctx.device->lpVtbl->CreateDepthStencilState(dx_ctx.device, &desc, &state->impl.depthStencilState);
}
{
D3D11_RASTERIZER_DESC rasterDesc;
rasterDesc.CullMode = convert_cull_mode(state->cull_mode);
rasterDesc.FillMode = D3D11_FILL_SOLID;
rasterDesc.FrontCounterClockwise = TRUE;
rasterDesc.DepthBias = 0;
rasterDesc.SlopeScaledDepthBias = 0.0f;
rasterDesc.DepthBiasClamp = 0.0f;
rasterDesc.DepthClipEnable = TRUE;
rasterDesc.ScissorEnable = FALSE;
rasterDesc.MultisampleEnable = FALSE;
rasterDesc.AntialiasedLineEnable = FALSE;
dx_ctx.device->lpVtbl->CreateRasterizerState(dx_ctx.device, &rasterDesc, &state->impl.rasterizerState);
rasterDesc.ScissorEnable = TRUE;
dx_ctx.device->lpVtbl->CreateRasterizerState(dx_ctx.device, &rasterDesc, &state->impl.rasterizerStateScissor);
// We need d3d11_3 for conservative raster
// D3D11_RASTERIZER_DESC2 rasterDesc;
// rasterDesc.ConservativeRaster = conservativeRasterization ? D3D11_CONSERVATIVE_RASTERIZATION_MODE_ON : D3D11_CONSERVATIVE_RASTERIZATION_MODE_OFF;
// dx_ctx.device->CreateRasterizerState2(&rasterDesc, &rasterizerState);
// rasterDesc.ScissorEnable = TRUE;
// dx_ctx.device->CreateRasterizerState2(&rasterDesc, &rasterizerStateScissor);
}
{
bool independentBlend = false;
for (int i = 1; i < 8; ++i) {
if (state->color_write_mask_red[0] != state->color_write_mask_red[i] || state->color_write_mask_green[0] != state->color_write_mask_green[i] ||
state->color_write_mask_blue[0] != state->color_write_mask_blue[i] || state->color_write_mask_alpha[0] != state->color_write_mask_alpha[i]) {
independentBlend = true;
break;
}
}
D3D11_BLEND_DESC blendDesc;
memset(&blendDesc, 0, sizeof(blendDesc));
blendDesc.AlphaToCoverageEnable = false;
blendDesc.IndependentBlendEnable = independentBlend;
D3D11_RENDER_TARGET_BLEND_DESC rtbd[8];
memset(&rtbd, 0, sizeof(rtbd));
createRenderTargetBlendDesc(state, &rtbd[0], 0);
blendDesc.RenderTarget[0] = rtbd[0];
if (independentBlend) {
for (int i = 1; i < 8; ++i) {
createRenderTargetBlendDesc(state, &rtbd[i], i);
blendDesc.RenderTarget[i] = rtbd[i];
}
}
dx_ctx.device->lpVtbl->CreateBlendState(dx_ctx.device, &blendDesc, &state->impl.blendState);
}
}

View File

@ -0,0 +1,37 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
struct ID3D11InputLayout;
struct ID3D11PixelShader;
struct ID3D11VertexShader;
struct ID3D11Buffer;
struct ID3D11DepthStencilState;
struct ID3D11RasterizerState;
struct ID3D11BlendState;
typedef struct {
// PipelineStateImpl();
//~PipelineStateImpl();
struct ID3D11InputLayout *d3d11inputLayout;
struct ID3D11Buffer *fragmentConstantBuffer;
struct ID3D11Buffer *vertexConstantBuffer;
struct ID3D11Buffer *geometryConstantBuffer;
struct ID3D11Buffer *tessEvalConstantBuffer;
struct ID3D11Buffer *tessControlConstantBuffer;
struct ID3D11DepthStencilState *depthStencilState;
struct ID3D11RasterizerState *rasterizerState;
struct ID3D11RasterizerState *rasterizerStateScissor;
struct ID3D11BlendState *blendState;
// void set(Graphics4::PipelineState* pipeline, bool scissoring);
// void setRasterizerState(bool scissoring);
// static void setConstants();
} kinc_g4_pipeline_impl_t;
void kinc_internal_set_constants(void);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,468 @@
#include <kinc/error.h>
#include <kinc/graphics4/rendertarget.h>
#include <kinc/log.h>
static DXGI_FORMAT convertRenderTargetFormat(kinc_g4_render_target_format_t format) {
switch (format) {
case KINC_G4_RENDER_TARGET_FORMAT_128BIT_FLOAT:
return DXGI_FORMAT_R32G32B32A32_FLOAT;
case KINC_G4_RENDER_TARGET_FORMAT_64BIT_FLOAT:
return DXGI_FORMAT_R16G16B16A16_FLOAT;
case KINC_G4_RENDER_TARGET_FORMAT_32BIT_RED_FLOAT:
return DXGI_FORMAT_R32_FLOAT;
case KINC_G4_RENDER_TARGET_FORMAT_16BIT_RED_FLOAT:
return DXGI_FORMAT_R16_FLOAT;
case KINC_G4_RENDER_TARGET_FORMAT_8BIT_RED:
return DXGI_FORMAT_R8_UNORM;
case KINC_G4_RENDER_TARGET_FORMAT_32BIT:
default:
return DXGI_FORMAT_R8G8B8A8_UNORM;
}
}
static int formatRenderTargetByteSize(kinc_g4_render_target_format_t format) {
switch (format) {
case KINC_G4_RENDER_TARGET_FORMAT_128BIT_FLOAT:
return 16;
case KINC_G4_RENDER_TARGET_FORMAT_64BIT_FLOAT:
return 8;
case KINC_G4_RENDER_TARGET_FORMAT_32BIT_RED_FLOAT:
return 4;
case KINC_G4_RENDER_TARGET_FORMAT_16BIT_RED_FLOAT:
return 2;
case KINC_G4_RENDER_TARGET_FORMAT_8BIT_RED:
return 1;
case KINC_G4_RENDER_TARGET_FORMAT_32BIT:
default:
return 4;
}
}
void kinc_g4_render_target_init_with_multisampling(kinc_g4_render_target_t *renderTarget, int width, int height, kinc_g4_render_target_format_t format,
int depthBufferBits, int stencilBufferBits, int samples_per_pixel) {
renderTarget->isCubeMap = false;
renderTarget->isDepthAttachment = false;
renderTarget->texWidth = renderTarget->width = width;
renderTarget->texHeight = renderTarget->height = height;
renderTarget->impl.format = format;
renderTarget->impl.textureStaging = NULL;
D3D11_TEXTURE2D_DESC desc;
desc.Width = width;
desc.Height = height;
desc.MipLevels = desc.ArraySize = 1;
desc.Format = convertRenderTargetFormat(format);
if (format == KINC_G4_RENDER_TARGET_FORMAT_16BIT_DEPTH) {
renderTarget->isDepthAttachment = true;
depthBufferBits = 16;
stencilBufferBits = 0;
}
bool antialiasing = samples_per_pixel > 1;
if (antialiasing) {
desc.SampleDesc.Count = samples_per_pixel;
desc.SampleDesc.Quality = D3D11_STANDARD_MULTISAMPLE_PATTERN;
}
else {
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
}
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = 0; // D3D11_CPU_ACCESS_WRITE;
desc.MiscFlags = 0;
renderTarget->impl.textureRender = NULL;
renderTarget->impl.textureSample = NULL;
renderTarget->impl.renderTargetSRV = NULL;
for (int i = 0; i < 6; i++) {
renderTarget->impl.renderTargetViewRender[i] = NULL;
renderTarget->impl.renderTargetViewSample[i] = NULL;
}
if (!renderTarget->isDepthAttachment) {
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &desc, NULL, &renderTarget->impl.textureRender));
D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
renderTargetViewDesc.Format = desc.Format;
renderTargetViewDesc.ViewDimension = antialiasing ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
renderTargetViewDesc.Texture2D.MipSlice = 0;
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateRenderTargetView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.textureRender,
&renderTargetViewDesc, &renderTarget->impl.renderTargetViewRender[0]));
if (antialiasing) {
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &desc, NULL, &renderTarget->impl.textureSample));
D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
renderTargetViewDesc.Format = desc.Format;
renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
renderTargetViewDesc.Texture2D.MipSlice = 0;
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateRenderTargetView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.textureSample,
&renderTargetViewDesc, &renderTarget->impl.renderTargetViewSample[0]));
}
else {
renderTarget->impl.textureSample = renderTarget->impl.textureRender;
renderTarget->impl.renderTargetViewSample[0] = renderTarget->impl.renderTargetViewRender[0];
}
}
renderTarget->impl.depthStencil = NULL;
renderTarget->impl.depthStencilSRV = NULL;
for (int i = 0; i < 6; i++) {
renderTarget->impl.depthStencilView[i] = NULL;
}
DXGI_FORMAT depthFormat;
DXGI_FORMAT depthViewFormat;
DXGI_FORMAT depthResourceFormat;
if (depthBufferBits == 16 && stencilBufferBits == 0) {
depthFormat = DXGI_FORMAT_R16_TYPELESS;
depthViewFormat = DXGI_FORMAT_D16_UNORM;
depthResourceFormat = DXGI_FORMAT_R16_UNORM;
}
else {
depthFormat = DXGI_FORMAT_R24G8_TYPELESS;
depthViewFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
depthResourceFormat = DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
}
if (depthBufferBits > 0) {
D3D11_TEXTURE2D_DESC depthStencilDesc;
depthStencilDesc.Format = depthFormat;
depthStencilDesc.Width = width;
depthStencilDesc.Height = height;
depthStencilDesc.ArraySize = 1;
depthStencilDesc.MipLevels = 1;
depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
depthStencilDesc.CPUAccessFlags = 0;
depthStencilDesc.MiscFlags = 0;
if (antialiasing) {
depthStencilDesc.SampleDesc.Count = 4;
depthStencilDesc.SampleDesc.Quality = D3D11_STANDARD_MULTISAMPLE_PATTERN;
}
else {
depthStencilDesc.SampleDesc.Count = 1;
depthStencilDesc.SampleDesc.Quality = 0;
}
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &depthStencilDesc, NULL, &renderTarget->impl.depthStencil));
D3D11_DEPTH_STENCIL_VIEW_DESC viewDesc;
viewDesc.Format = depthViewFormat;
viewDesc.ViewDimension = antialiasing ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D;
viewDesc.Flags = 0;
if (!antialiasing) {
viewDesc.Texture2D.MipSlice = 0;
}
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateDepthStencilView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.depthStencil, &viewDesc,
&renderTarget->impl.depthStencilView[0]));
}
D3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc;
if (!renderTarget->isDepthAttachment) {
shaderResourceViewDesc.Format = desc.Format;
shaderResourceViewDesc.ViewDimension = antialiasing ? D3D11_SRV_DIMENSION_TEXTURE2DMS : D3D11_SRV_DIMENSION_TEXTURE2D;
shaderResourceViewDesc.Texture2D.MostDetailedMip = 0;
shaderResourceViewDesc.Texture2D.MipLevels = 1;
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateShaderResourceView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.textureSample,
&shaderResourceViewDesc, &renderTarget->impl.renderTargetSRV));
}
if (depthBufferBits > 0) {
shaderResourceViewDesc.Format = depthResourceFormat;
shaderResourceViewDesc.ViewDimension = antialiasing ? D3D11_SRV_DIMENSION_TEXTURE2DMS : D3D11_SRV_DIMENSION_TEXTURE2D;
shaderResourceViewDesc.Texture2D.MostDetailedMip = 0;
shaderResourceViewDesc.Texture2D.MipLevels = 1;
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateShaderResourceView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.depthStencil,
&shaderResourceViewDesc, &renderTarget->impl.depthStencilSRV));
}
if (renderTarget->impl.renderTargetViewRender[0] != NULL) {
FLOAT colors[4] = {0, 0, 0, 0};
dx_ctx.context->lpVtbl->ClearRenderTargetView(dx_ctx.context, renderTarget->impl.renderTargetViewRender[0], colors);
}
}
void kinc_g4_render_target_init_cube_with_multisampling(kinc_g4_render_target_t *renderTarget, int cubeMapSize, kinc_g4_render_target_format_t format,
int depthBufferBits, int stencilBufferBits, int samples_per_pixel) {
renderTarget->width = cubeMapSize;
renderTarget->height = cubeMapSize;
renderTarget->isCubeMap = true;
renderTarget->isDepthAttachment = false;
renderTarget->texWidth = renderTarget->width;
renderTarget->texHeight = renderTarget->height;
renderTarget->impl.format = format;
renderTarget->impl.textureStaging = NULL;
D3D11_TEXTURE2D_DESC desc;
desc.Width = renderTarget->width;
desc.Height = renderTarget->height;
desc.MipLevels = 1;
desc.ArraySize = 6;
desc.Format = convertRenderTargetFormat(format);
if (format == KINC_G4_RENDER_TARGET_FORMAT_16BIT_DEPTH) {
renderTarget->isDepthAttachment = true;
depthBufferBits = 16;
stencilBufferBits = 0;
}
bool antialiasing = samples_per_pixel > 1;
if (antialiasing) {
desc.SampleDesc.Count = samples_per_pixel;
desc.SampleDesc.Quality = D3D11_STANDARD_MULTISAMPLE_PATTERN;
}
else {
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
}
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = 0; // D3D11_CPU_ACCESS_WRITE;
desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
renderTarget->impl.textureRender = NULL;
renderTarget->impl.textureSample = NULL;
renderTarget->impl.renderTargetSRV = NULL;
for (int i = 0; i < 6; i++) {
renderTarget->impl.renderTargetViewRender[i] = NULL;
renderTarget->impl.renderTargetViewSample[i] = NULL;
}
if (!renderTarget->isDepthAttachment) {
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &desc, NULL, &renderTarget->impl.textureRender));
D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
renderTargetViewDesc.Format = desc.Format;
renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
renderTargetViewDesc.Texture2DArray.MipSlice = 0;
renderTargetViewDesc.Texture2DArray.ArraySize = 1;
for (int i = 0; i < 6; i++) {
renderTargetViewDesc.Texture2DArray.FirstArraySlice = i;
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateRenderTargetView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.textureRender,
&renderTargetViewDesc, &renderTarget->impl.renderTargetViewRender[i]));
}
if (antialiasing) {
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &desc, NULL, &renderTarget->impl.textureSample));
D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
renderTargetViewDesc.Format = desc.Format;
renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
renderTargetViewDesc.Texture2D.MipSlice = 0;
renderTargetViewDesc.Texture2DArray.ArraySize = 1;
for (int i = 0; i < 6; i++) {
renderTargetViewDesc.Texture2DArray.FirstArraySlice = i;
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateRenderTargetView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.textureSample,
&renderTargetViewDesc, &renderTarget->impl.renderTargetViewSample[i]));
}
}
else {
renderTarget->impl.textureSample = renderTarget->impl.textureRender;
for (int i = 0; i < 6; i++) {
renderTarget->impl.renderTargetViewSample[i] = renderTarget->impl.renderTargetViewRender[i];
}
}
}
renderTarget->impl.depthStencil = NULL;
renderTarget->impl.depthStencilSRV = NULL;
for (int i = 0; i < 6; i++) {
renderTarget->impl.depthStencilView[i] = NULL;
}
DXGI_FORMAT depthFormat;
DXGI_FORMAT depthViewFormat;
DXGI_FORMAT depthResourceFormat;
if (depthBufferBits == 16 && stencilBufferBits == 0) {
depthFormat = DXGI_FORMAT_R16_TYPELESS;
depthViewFormat = DXGI_FORMAT_D16_UNORM;
depthResourceFormat = DXGI_FORMAT_R16_UNORM;
}
else {
depthFormat = DXGI_FORMAT_R24G8_TYPELESS;
depthViewFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
depthResourceFormat = DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
}
if (depthBufferBits > 0) {
D3D11_TEXTURE2D_DESC depthStencilDesc;
depthStencilDesc.Format = depthFormat;
depthStencilDesc.Width = renderTarget->width;
depthStencilDesc.Height = renderTarget->height;
depthStencilDesc.ArraySize = 1;
depthStencilDesc.MipLevels = 1;
depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
depthStencilDesc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
depthStencilDesc.CPUAccessFlags = 0;
depthStencilDesc.ArraySize = 6;
if (antialiasing) {
depthStencilDesc.SampleDesc.Count = 4;
depthStencilDesc.SampleDesc.Quality = D3D11_STANDARD_MULTISAMPLE_PATTERN;
}
else {
depthStencilDesc.SampleDesc.Count = 1;
depthStencilDesc.SampleDesc.Quality = 0;
}
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &depthStencilDesc, NULL, &renderTarget->impl.depthStencil));
D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc;
depthStencilViewDesc.Format = depthViewFormat;
depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
depthStencilViewDesc.Texture2DArray.MipSlice = 0;
depthStencilViewDesc.Texture2DArray.ArraySize = 1;
depthStencilViewDesc.Flags = 0;
for (int i = 0; i < 6; i++) {
depthStencilViewDesc.Texture2DArray.FirstArraySlice = i;
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateDepthStencilView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.depthStencil,
&depthStencilViewDesc, &renderTarget->impl.depthStencilView[i]));
}
}
D3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc;
if (!renderTarget->isDepthAttachment) {
shaderResourceViewDesc.Format = desc.Format;
shaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
shaderResourceViewDesc.TextureCube.MostDetailedMip = 0;
shaderResourceViewDesc.TextureCube.MipLevels = 1;
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateShaderResourceView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.textureSample,
&shaderResourceViewDesc, &renderTarget->impl.renderTargetSRV));
}
if (depthBufferBits > 0) {
shaderResourceViewDesc.Format = depthResourceFormat;
shaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
shaderResourceViewDesc.TextureCube.MostDetailedMip = 0;
shaderResourceViewDesc.TextureCube.MipLevels = 1;
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateShaderResourceView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.depthStencil,
&shaderResourceViewDesc, &renderTarget->impl.depthStencilSRV));
}
if (!renderTarget->isDepthAttachment) {
FLOAT colors[4] = {0, 0, 0, 0};
for (int i = 0; i < 6; i++) {
dx_ctx.context->lpVtbl->ClearRenderTargetView(dx_ctx.context, renderTarget->impl.renderTargetViewRender[i], colors);
}
}
}
void kinc_g4_render_target_destroy(kinc_g4_render_target_t *renderTarget) {
for (int i = 0; i < 6; i++) {
if (renderTarget->impl.renderTargetViewRender[i] != NULL)
renderTarget->impl.renderTargetViewRender[i]->lpVtbl->Release(renderTarget->impl.renderTargetViewRender[i]);
if (renderTarget->impl.renderTargetViewSample[i] != NULL &&
renderTarget->impl.renderTargetViewSample[i] != renderTarget->impl.renderTargetViewRender[i])
renderTarget->impl.renderTargetViewSample[i]->lpVtbl->Release(renderTarget->impl.renderTargetViewSample[i]);
if (renderTarget->impl.depthStencilView[i] != NULL)
renderTarget->impl.depthStencilView[i]->lpVtbl->Release(renderTarget->impl.depthStencilView[i]);
}
if (renderTarget->impl.renderTargetSRV != NULL)
renderTarget->impl.renderTargetSRV->lpVtbl->Release(renderTarget->impl.renderTargetSRV);
if (renderTarget->impl.depthStencilSRV != NULL)
renderTarget->impl.depthStencilSRV->lpVtbl->Release(renderTarget->impl.depthStencilSRV);
if (renderTarget->impl.depthStencil != NULL)
renderTarget->impl.depthStencil->lpVtbl->Release(renderTarget->impl.depthStencil);
if (renderTarget->impl.textureRender != NULL)
renderTarget->impl.textureRender->lpVtbl->Release(renderTarget->impl.textureRender);
if (renderTarget->impl.textureStaging != NULL)
renderTarget->impl.textureStaging->lpVtbl->Release(renderTarget->impl.textureStaging);
if (renderTarget->impl.textureSample != NULL && renderTarget->impl.textureSample != renderTarget->impl.textureRender)
renderTarget->impl.textureSample->lpVtbl->Release(renderTarget->impl.textureSample);
}
#ifdef KINC_KONG
void kinc_g4_render_target_use_color_as_texture(kinc_g4_render_target_t *renderTarget, uint32_t unit) {
if (renderTarget->impl.textureSample != renderTarget->impl.textureRender) {
dx_ctx.context->lpVtbl->ResolveSubresource(dx_ctx.context, (ID3D11Resource *)renderTarget->impl.textureSample, 0,
(ID3D11Resource *)renderTarget->impl.textureRender, 0, DXGI_FORMAT_R8G8B8A8_UNORM);
}
dx_ctx.context->lpVtbl->PSSetShaderResources(dx_ctx.context, unit, 1,
renderTarget->isDepthAttachment ? &renderTarget->impl.depthStencilSRV : &renderTarget->impl.renderTargetSRV);
}
#else
void kinc_g4_render_target_use_color_as_texture(kinc_g4_render_target_t *renderTarget, kinc_g4_texture_unit_t unit) {
if (unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] < 0 && unit.stages[KINC_G4_SHADER_TYPE_VERTEX] < 0)
return;
if (renderTarget->impl.textureSample != renderTarget->impl.textureRender) {
dx_ctx.context->lpVtbl->ResolveSubresource(dx_ctx.context, (ID3D11Resource *)renderTarget->impl.textureSample, 0,
(ID3D11Resource *)renderTarget->impl.textureRender, 0, DXGI_FORMAT_R8G8B8A8_UNORM);
}
if (unit.stages[KINC_G4_SHADER_TYPE_VERTEX] >= 0) {
dx_ctx.context->lpVtbl->VSSetShaderResources(dx_ctx.context, unit.stages[KINC_G4_SHADER_TYPE_VERTEX], 1,
renderTarget->isDepthAttachment ? &renderTarget->impl.depthStencilSRV
: &renderTarget->impl.renderTargetSRV);
}
if (unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] >= 0) {
dx_ctx.context->lpVtbl->PSSetShaderResources(dx_ctx.context, unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], 1,
renderTarget->isDepthAttachment ? &renderTarget->impl.depthStencilSRV
: &renderTarget->impl.renderTargetSRV);
}
}
#endif
void kinc_g4_render_target_use_depth_as_texture(kinc_g4_render_target_t *renderTarget, kinc_g4_texture_unit_t unit) {
if (unit.stages[KINC_G4_SHADER_TYPE_VERTEX] >= 0) {
dx_ctx.context->lpVtbl->VSSetShaderResources(dx_ctx.context, unit.stages[KINC_G4_SHADER_TYPE_VERTEX], 1, &renderTarget->impl.depthStencilSRV);
}
if (unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] >= 0) {
dx_ctx.context->lpVtbl->PSSetShaderResources(dx_ctx.context, unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], 1, &renderTarget->impl.depthStencilSRV);
}
}
void kinc_g4_render_target_set_depth_stencil_from(kinc_g4_render_target_t *renderTarget, kinc_g4_render_target_t *source) {
renderTarget->impl.depthStencil = source->impl.depthStencil;
for (int i = 0; i < 6; i++) {
renderTarget->impl.depthStencilView[i] = source->impl.depthStencilView[i];
}
renderTarget->impl.depthStencilSRV = source->impl.depthStencilSRV;
}
void kinc_g4_render_target_get_pixels(kinc_g4_render_target_t *renderTarget, uint8_t *data) {
if (renderTarget->impl.textureStaging == NULL) {
D3D11_TEXTURE2D_DESC desc;
desc.Width = renderTarget->texWidth;
desc.Height = renderTarget->texHeight;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = convertRenderTargetFormat((kinc_g4_render_target_format_t)renderTarget->impl.format);
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_STAGING;
desc.BindFlags = 0;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
desc.MiscFlags = 0;
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &desc, NULL, &renderTarget->impl.textureStaging));
}
D3D11_BOX sourceRegion;
sourceRegion.left = 0;
sourceRegion.right = renderTarget->texWidth;
sourceRegion.top = 0;
sourceRegion.bottom = renderTarget->texHeight;
sourceRegion.front = 0;
sourceRegion.back = 1;
dx_ctx.context->lpVtbl->CopySubresourceRegion(dx_ctx.context, (ID3D11Resource *)renderTarget->impl.textureStaging, 0, 0, 0, 0,
(ID3D11Resource *)renderTarget->impl.textureRender, 0, &sourceRegion);
D3D11_MAPPED_SUBRESOURCE mappedResource;
dx_ctx.context->lpVtbl->Map(dx_ctx.context, (ID3D11Resource *)renderTarget->impl.textureStaging, 0, D3D11_MAP_READ, 0, &mappedResource);
int size;
if (mappedResource.RowPitch != 0) {
size = mappedResource.RowPitch * renderTarget->texHeight;
}
else {
size = renderTarget->texWidth * renderTarget->texHeight * formatRenderTargetByteSize((kinc_g4_render_target_format_t)renderTarget->impl.format);
}
memcpy(data, mappedResource.pData, size);
dx_ctx.context->lpVtbl->Unmap(dx_ctx.context, (ID3D11Resource *)renderTarget->impl.textureStaging, 0);
}
void kinc_g4_render_target_generate_mipmaps(kinc_g4_render_target_t *renderTarget, int levels) {}

View File

@ -0,0 +1,27 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
struct ID3D11Texture2D;
struct ID3D11RenderTargetView;
struct ID3D11DepthStencilView;
struct ID3D11ShaderResourceView;
typedef struct {
struct ID3D11Texture2D *textureRender;
struct ID3D11Texture2D *textureSample;
struct ID3D11Texture2D *textureStaging;
struct ID3D11RenderTargetView *renderTargetViewRender[6];
struct ID3D11RenderTargetView *renderTargetViewSample[6];
struct ID3D11Texture2D *depthStencil;
struct ID3D11DepthStencilView *depthStencilView[6];
struct ID3D11ShaderResourceView *renderTargetSRV;
struct ID3D11ShaderResourceView *depthStencilSRV;
int format;
} kinc_g4_render_target_impl_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,114 @@
#include <kinc/graphics4/shader.h>
void kinc_g4_shader_destroy(kinc_g4_shader_t *shader) {
if (shader->impl.shader != NULL) {
((IUnknown *)shader->impl.shader)->lpVtbl->Release(shader->impl.shader);
free(shader->impl.data);
}
}
void kinc_g4_shader_init(kinc_g4_shader_t *shader, const void *_data, size_t length, kinc_g4_shader_type_t type) {
unsigned index = 0;
uint8_t *data = (uint8_t *)_data;
shader->impl.type = (int)type;
#ifndef KINC_KONG
memset(&shader->impl.attributes, 0, sizeof(shader->impl.attributes));
int attributesCount = data[index++];
for (int i = 0; i < attributesCount; ++i) {
unsigned char name[256];
for (unsigned i2 = 0; i2 < 255; ++i2) {
name[i2] = data[index++];
if (name[i2] == 0)
break;
}
shader->impl.attributes[i].hash = kinc_internal_hash_name(name);
shader->impl.attributes[i].index = data[index++];
}
memset(&shader->impl.textures, 0, sizeof(shader->impl.textures));
uint8_t texCount = data[index++];
for (unsigned i = 0; i < texCount; ++i) {
unsigned char name[256];
for (unsigned i2 = 0; i2 < 255; ++i2) {
name[i2] = data[index++];
if (name[i2] == 0)
break;
}
shader->impl.textures[i].hash = kinc_internal_hash_name(name);
shader->impl.textures[i].index = data[index++];
}
memset(&shader->impl.constants, 0, sizeof(shader->impl.constants));
uint8_t constantCount = data[index++];
shader->impl.constantsSize = 0;
for (unsigned i = 0; i < constantCount; ++i) {
unsigned char name[256];
for (unsigned i2 = 0; i2 < 255; ++i2) {
name[i2] = data[index++];
if (name[i2] == 0)
break;
}
kinc_internal_shader_constant_t constant;
constant.hash = kinc_internal_hash_name(name);
constant.offset = *(uint32_t *)&data[index];
index += 4;
constant.size = *(uint32_t *)&data[index];
index += 4;
constant.columns = data[index];
index += 1;
constant.rows = data[index];
index += 1;
shader->impl.constants[i] = constant;
shader->impl.constantsSize = constant.offset + constant.size;
}
#endif
shader->impl.length = (int)(length - index);
shader->impl.data = (uint8_t *)malloc(shader->impl.length);
assert(shader->impl.data != NULL);
memcpy(shader->impl.data, &data[index], shader->impl.length);
switch (type) {
case KINC_G4_SHADER_TYPE_VERTEX:
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateVertexShader(dx_ctx.device, shader->impl.data, shader->impl.length, NULL,
(ID3D11VertexShader **)&shader->impl.shader));
break;
case KINC_G4_SHADER_TYPE_FRAGMENT:
kinc_microsoft_affirm(
dx_ctx.device->lpVtbl->CreatePixelShader(dx_ctx.device, shader->impl.data, shader->impl.length, NULL, (ID3D11PixelShader **)&shader->impl.shader));
break;
case KINC_G4_SHADER_TYPE_GEOMETRY:
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateGeometryShader(dx_ctx.device, shader->impl.data, shader->impl.length, NULL,
(ID3D11GeometryShader **)&shader->impl.shader));
break;
case KINC_G4_SHADER_TYPE_TESSELLATION_CONTROL:
kinc_microsoft_affirm(
dx_ctx.device->lpVtbl->CreateHullShader(dx_ctx.device, shader->impl.data, shader->impl.length, NULL, (ID3D11HullShader **)&shader->impl.shader));
break;
case KINC_G4_SHADER_TYPE_TESSELLATION_EVALUATION:
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateDomainShader(dx_ctx.device, shader->impl.data, shader->impl.length, NULL,
(ID3D11DomainShader **)&shader->impl.shader));
break;
}
}
#ifdef KRAFIX_LIBRARY
extern int krafix_compile(const char *source, char *output, int *length, const char *targetlang, const char *system, const char *shadertype, int version);
#endif
int kinc_g4_shader_init_from_source(kinc_g4_shader_t *shader, const char *source, kinc_g4_shader_type_t type) {
#ifdef KRAFIX_LIBRARY
char *output = malloc(1024 * 1024);
int length;
int errors = krafix_compile(source, output, &length, "d3d11", "windows", type == KINC_G4_SHADER_TYPE_FRAGMENT ? "frag" : "vert", -1);
if (errors > 0) {
return errors;
}
kinc_g4_shader_init(shader, output, length, type);
return 0;
#else
return 0;
#endif
}

View File

@ -0,0 +1,58 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include <kinc/backend/graphics4/ShaderHash.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
uint32_t hash;
uint32_t offset;
uint32_t size;
uint8_t columns;
uint8_t rows;
} kinc_internal_shader_constant_t;
typedef struct {
#ifndef KINC_KONG
kinc_internal_shader_constant_t constants[64];
int constantsSize;
kinc_internal_hash_index_t attributes[64];
kinc_internal_hash_index_t textures[64];
#endif
void *shader;
uint8_t *data;
int length;
int type;
} kinc_g4_shader_impl_t;
typedef struct {
uint32_t vertexOffset;
uint32_t vertexSize;
uint32_t fragmentOffset;
uint32_t fragmentSize;
uint32_t geometryOffset;
uint32_t geometrySize;
uint32_t tessEvalOffset;
uint32_t tessEvalSize;
uint32_t tessControlOffset;
uint32_t tessControlSize;
uint8_t vertexColumns;
uint8_t vertexRows;
uint8_t fragmentColumns;
uint8_t fragmentRows;
uint8_t geometryColumns;
uint8_t geometryRows;
uint8_t tessEvalColumns;
uint8_t tessEvalRows;
uint8_t tessControlColumns;
uint8_t tessControlRows;
} kinc_g4_constant_location_impl_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,353 @@
#include <kinc/graphics4/texture.h>
#include <kinc/graphics4/textureunit.h>
#include <assert.h>
static kinc_g4_texture_t *setTextures[16] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
static DXGI_FORMAT convertFormat(kinc_image_format_t format) {
switch (format) {
case KINC_IMAGE_FORMAT_RGBA128:
return DXGI_FORMAT_R32G32B32A32_FLOAT;
case KINC_IMAGE_FORMAT_RGBA64:
return DXGI_FORMAT_R16G16B16A16_FLOAT;
case KINC_IMAGE_FORMAT_RGB24:
return DXGI_FORMAT_R8G8B8A8_UNORM;
case KINC_IMAGE_FORMAT_A32:
return DXGI_FORMAT_R32_FLOAT;
case KINC_IMAGE_FORMAT_A16:
return DXGI_FORMAT_R16_FLOAT;
case KINC_IMAGE_FORMAT_GREY8:
return DXGI_FORMAT_R8_UNORM;
case KINC_IMAGE_FORMAT_BGRA32:
return DXGI_FORMAT_B8G8R8A8_UNORM;
case KINC_IMAGE_FORMAT_RGBA32:
return DXGI_FORMAT_R8G8B8A8_UNORM;
default:
assert(false);
return DXGI_FORMAT_R8G8B8A8_UNORM;
}
}
static int formatByteSize(kinc_image_format_t format) {
switch (format) {
case KINC_IMAGE_FORMAT_RGBA128:
return 16;
case KINC_IMAGE_FORMAT_RGBA64:
return 8;
case KINC_IMAGE_FORMAT_RGB24:
return 4;
case KINC_IMAGE_FORMAT_A32:
return 4;
case KINC_IMAGE_FORMAT_A16:
return 2;
case KINC_IMAGE_FORMAT_GREY8:
return 1;
case KINC_IMAGE_FORMAT_BGRA32:
case KINC_IMAGE_FORMAT_RGBA32:
return 4;
default:
assert(false);
return 4;
}
}
static bool isHdr(kinc_image_format_t format) {
return format == KINC_IMAGE_FORMAT_RGBA128 || format == KINC_IMAGE_FORMAT_RGBA64 || format == KINC_IMAGE_FORMAT_A32 || format == KINC_IMAGE_FORMAT_A16;
}
void kinc_g4_texture_init_from_image(kinc_g4_texture_t *texture, kinc_image_t *image) {
memset(&texture->impl, 0, sizeof(texture->impl));
texture->impl.stage = 0;
texture->tex_width = image->width;
texture->tex_height = image->height;
texture->tex_depth = 1;
texture->format = image->format;
texture->impl.rowPitch = 0;
D3D11_TEXTURE2D_DESC desc;
desc.Width = image->width;
desc.Height = image->height;
desc.MipLevels = desc.ArraySize = 1;
desc.Format = convertFormat(image->format);
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = 0; // D3D11_CPU_ACCESS_WRITE;
desc.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA data;
data.pSysMem = image->data;
data.SysMemPitch = image->width * formatByteSize(image->format);
data.SysMemSlicePitch = 0;
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &desc, &data, &texture->impl.texture));
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateShaderResourceView(dx_ctx.device, (ID3D11Resource *)texture->impl.texture, NULL, &texture->impl.view));
}
void kinc_g4_texture_init_from_image3d(kinc_g4_texture_t *texture, kinc_image_t *image) {
memset(&texture->impl, 0, sizeof(texture->impl));
texture->impl.stage = 0;
texture->tex_width = image->width;
texture->tex_height = image->height;
texture->tex_depth = image->depth;
texture->format = image->format;
texture->impl.rowPitch = 0;
D3D11_TEXTURE3D_DESC desc;
desc.Width = image->width;
desc.Height = image->height;
desc.Depth = image->depth;
desc.MipLevels = 1;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.MiscFlags = 0;
desc.Format = convertFormat(image->format);
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.CPUAccessFlags = 0;
D3D11_SUBRESOURCE_DATA data;
data.pSysMem = image->data;
data.SysMemPitch = image->width * formatByteSize(image->format);
data.SysMemSlicePitch = image->width * image->height * formatByteSize(image->format);
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture3D(dx_ctx.device, &desc, &data, &texture->impl.texture3D));
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateShaderResourceView(dx_ctx.device, (ID3D11Resource *)texture->impl.texture3D, NULL, &texture->impl.view));
}
void kinc_g4_texture_init(kinc_g4_texture_t *texture, int width, int height, kinc_image_format_t format) {
memset(&texture->impl, 0, sizeof(texture->impl));
texture->impl.stage = 0;
texture->tex_width = width;
texture->tex_height = height;
texture->tex_depth = 1;
texture->format = format;
D3D11_TEXTURE2D_DESC desc;
desc.Width = width;
desc.Height = height;
desc.MipLevels = desc.ArraySize = 1;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.MiscFlags = 0;
if (format == KINC_IMAGE_FORMAT_RGBA128) { // for compute
desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = 0;
}
else {
desc.Format = convertFormat(format);
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
desc.Usage = D3D11_USAGE_DYNAMIC;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
}
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &desc, NULL, &texture->impl.texture));
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateShaderResourceView(dx_ctx.device, (ID3D11Resource *)texture->impl.texture, NULL, &texture->impl.view));
if (format == KINC_IMAGE_FORMAT_RGBA128) {
D3D11_UNORDERED_ACCESS_VIEW_DESC du;
du.Format = desc.Format;
du.Texture2D.MipSlice = 0;
du.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
kinc_microsoft_affirm(
dx_ctx.device->lpVtbl->CreateUnorderedAccessView(dx_ctx.device, (ID3D11Resource *)texture->impl.texture, &du, &texture->impl.computeView));
}
}
void kinc_g4_texture_init3d(kinc_g4_texture_t *texture, int width, int height, int depth, kinc_image_format_t format) {
memset(&texture->impl, 0, sizeof(texture->impl));
texture->impl.stage = 0;
texture->tex_width = width;
texture->tex_height = height;
texture->tex_depth = depth;
texture->format = format;
texture->impl.hasMipmaps = true;
D3D11_TEXTURE3D_DESC desc;
desc.Width = width;
desc.Height = height;
desc.Depth = depth;
desc.MipLevels = 0;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;
desc.Format = format == KINC_IMAGE_FORMAT_RGBA32 ? DXGI_FORMAT_R8G8B8A8_UNORM : DXGI_FORMAT_R8_UNORM;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET | D3D11_BIND_UNORDERED_ACCESS;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.CPUAccessFlags = 0;
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture3D(dx_ctx.device, &desc, NULL, &texture->impl.texture3D));
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateShaderResourceView(dx_ctx.device, (ID3D11Resource *)texture->impl.texture3D, NULL, &texture->impl.view));
}
// TextureImpl::TextureImpl() : hasMipmaps(false), renderView(nullptr), computeView(nullptr) {}
void kinc_internal_texture_unset(kinc_g4_texture_t *texture);
void kinc_g4_texture_destroy(kinc_g4_texture_t *texture) {
kinc_internal_texture_unset(texture);
if (texture->impl.view != NULL) {
texture->impl.view->lpVtbl->Release(texture->impl.view);
}
if (texture->impl.texture != NULL) {
texture->impl.texture->lpVtbl->Release(texture->impl.texture);
}
if (texture->impl.texture3D != NULL) {
texture->impl.texture3D->lpVtbl->Release(texture->impl.texture3D);
}
if (texture->impl.computeView != NULL) {
texture->impl.computeView->lpVtbl->Release(texture->impl.computeView);
}
}
void kinc_internal_texture_unmipmap(kinc_g4_texture_t *texture) {
texture->impl.hasMipmaps = false;
}
#ifdef KINC_KONG
void kinc_internal_texture_set(kinc_g4_texture_t *texture, uint32_t unit) {
dx_ctx.context->lpVtbl->PSSetShaderResources(dx_ctx.context, unit, 1, &texture->impl.view);
texture->impl.stage = unit;
setTextures[unit] = texture;
}
#else
void kinc_internal_texture_set(kinc_g4_texture_t *texture, kinc_g4_texture_unit_t unit) {
if (unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] < 0 && unit.stages[KINC_G4_SHADER_TYPE_VERTEX] < 0)
return;
if (unit.stages[KINC_G4_SHADER_TYPE_VERTEX] >= 0) {
dx_ctx.context->lpVtbl->VSSetShaderResources(dx_ctx.context, unit.stages[KINC_G4_SHADER_TYPE_VERTEX], 1, &texture->impl.view);
}
if (unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] >= 0) {
dx_ctx.context->lpVtbl->PSSetShaderResources(dx_ctx.context, unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], 1, &texture->impl.view);
}
texture->impl.stage = unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] >= 0 ? unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] : unit.stages[KINC_G4_SHADER_TYPE_VERTEX];
setTextures[texture->impl.stage] = texture;
}
#endif
void kinc_internal_texture_set_image(kinc_g4_texture_t *texture, kinc_g4_texture_unit_t unit) {
if (unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] < 0)
return;
if (texture->impl.computeView == NULL) {
D3D11_UNORDERED_ACCESS_VIEW_DESC du;
du.Format = texture->format == KINC_IMAGE_FORMAT_RGBA32 ? DXGI_FORMAT_R8G8B8A8_UNORM : DXGI_FORMAT_R8_UNORM;
du.Texture3D.MipSlice = 0;
du.Texture3D.FirstWSlice = 0;
du.Texture3D.WSize = -1;
du.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D;
kinc_microsoft_affirm(
dx_ctx.device->lpVtbl->CreateUnorderedAccessView(dx_ctx.device, (ID3D11Resource *)texture->impl.texture3D, &du, &texture->impl.computeView));
}
dx_ctx.context->lpVtbl->OMSetRenderTargetsAndUnorderedAccessViews(dx_ctx.context, 0, NULL, NULL, unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], 1,
&texture->impl.computeView, NULL);
}
void kinc_internal_texture_unset(kinc_g4_texture_t *texture) {
if (setTextures[texture->impl.stage] == texture) {
setTextures[texture->impl.stage] = NULL;
}
}
uint8_t *kinc_g4_texture_lock(kinc_g4_texture_t *texture) {
D3D11_MAPPED_SUBRESOURCE mappedResource;
kinc_microsoft_affirm(dx_ctx.context->lpVtbl->Map(dx_ctx.context, (ID3D11Resource *)texture->impl.texture, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource));
texture->impl.rowPitch = mappedResource.RowPitch;
return (uint8_t *)mappedResource.pData;
}
void kinc_g4_texture_unlock(kinc_g4_texture_t *texture) {
dx_ctx.context->lpVtbl->Unmap(dx_ctx.context, (ID3D11Resource *)texture->impl.texture, 0);
}
void kinc_g4_texture_clear(kinc_g4_texture_t *texture, int x, int y, int z, int width, int height, int depth, unsigned color) {
if (texture->impl.renderView == NULL) {
texture->tex_depth > 1 ? kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateRenderTargetView(dx_ctx.device, (ID3D11Resource *)texture->impl.texture3D,
0, &texture->impl.renderView))
: kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateRenderTargetView(dx_ctx.device, (ID3D11Resource *)texture->impl.texture, 0,
&texture->impl.renderView));
}
static float clearColor[4];
clearColor[0] = ((color & 0x00ff0000) >> 16) / 255.0f;
clearColor[1] = ((color & 0x0000ff00) >> 8) / 255.0f;
clearColor[2] = (color & 0x000000ff) / 255.0f;
clearColor[3] = ((color & 0xff000000) >> 24) / 255.0f;
dx_ctx.context->lpVtbl->ClearRenderTargetView(dx_ctx.context, texture->impl.renderView, clearColor);
}
int kinc_g4_texture_stride(kinc_g4_texture_t *texture) {
assert(texture->impl.rowPitch != 0); // stride is not yet set, lock and unlock the texture first (or find a good fix for this and send a PR)
return texture->impl.rowPitch;
}
static void enableMipmaps(kinc_g4_texture_t *texture, int texWidth, int texHeight, int format) {
D3D11_TEXTURE2D_DESC desc;
desc.Width = texWidth;
desc.Height = texHeight;
desc.MipLevels = 0;
desc.ArraySize = 1;
desc.Format = convertFormat((kinc_image_format_t)format);
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
desc.CPUAccessFlags = 0;
desc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;
ID3D11Texture2D *mipMappedTexture;
ID3D11ShaderResourceView *mipMappedView;
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &desc, NULL, &mipMappedTexture));
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateShaderResourceView(dx_ctx.device, (ID3D11Resource *)mipMappedTexture, NULL, &mipMappedView));
D3D11_BOX sourceRegion;
sourceRegion.left = 0;
sourceRegion.right = texWidth;
sourceRegion.top = 0;
sourceRegion.bottom = texHeight;
sourceRegion.front = 0;
sourceRegion.back = 1;
dx_ctx.context->lpVtbl->CopySubresourceRegion(dx_ctx.context, (ID3D11Resource *)mipMappedTexture, 0, 0, 0, 0, (ID3D11Resource *)texture->impl.texture, 0,
&sourceRegion);
if (texture->impl.texture != NULL) {
texture->impl.texture->lpVtbl->Release(texture->impl.texture);
}
texture->impl.texture = mipMappedTexture;
if (texture->impl.view != NULL) {
texture->impl.view->lpVtbl->Release(texture->impl.view);
}
texture->impl.view = mipMappedView;
texture->impl.hasMipmaps = true;
}
void kinc_g4_texture_generate_mipmaps(kinc_g4_texture_t *texture, int levels) {
if (!texture->impl.hasMipmaps) {
enableMipmaps(texture, texture->tex_width, texture->tex_height, texture->format);
}
dx_ctx.context->lpVtbl->GenerateMips(dx_ctx.context, texture->impl.view);
}
void kinc_g4_texture_set_mipmap(kinc_g4_texture_t *texture, kinc_image_t *mipmap, int level) {
if (!texture->impl.hasMipmaps) {
enableMipmaps(texture, texture->tex_width, texture->tex_height, texture->format);
}
D3D11_BOX dstRegion;
dstRegion.left = 0;
dstRegion.right = mipmap->width;
dstRegion.top = 0;
dstRegion.bottom = mipmap->height;
dstRegion.front = 0;
dstRegion.back = 1;
dx_ctx.context->lpVtbl->UpdateSubresource(dx_ctx.context, (ID3D11Resource *)texture->impl.texture, level, &dstRegion, mipmap->data,
mipmap->width * formatByteSize(mipmap->format), 0);
}

View File

@ -0,0 +1,24 @@
#pragma once
struct ID3D11Texture2D;
struct ID3D11Texture3D;
struct ID3D11ShaderResourceView;
struct ID3D11UnorderedAccessView;
struct ID3D11RenderTargetView;
// TextureImpl();
//~TextureImpl();
// void enableMipmaps(int texWidth, int texHeight, int format);
// void unmipmap();
// void unset();
typedef struct {
bool hasMipmaps;
int stage;
struct ID3D11Texture2D *texture;
struct ID3D11Texture3D *texture3D;
struct ID3D11ShaderResourceView *view;
struct ID3D11UnorderedAccessView *computeView;
struct ID3D11RenderTargetView *renderView;
int rowPitch;
} kinc_g4_texture_impl_t;

View File

@ -0,0 +1,39 @@
#include <kinc/graphics4/texturearray.h>
#include <kinc/graphics4/textureunit.h>
void kinc_g4_texture_array_init(kinc_g4_texture_array_t *array, kinc_image_t *textures, int count) {
D3D11_TEXTURE2D_DESC desc;
desc.Width = textures[0].width;
desc.Height = textures[0].height;
desc.MipLevels = 1;
desc.ArraySize = 2;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = 0;
desc.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA *resdata = (D3D11_SUBRESOURCE_DATA *)alloca(sizeof(D3D11_SUBRESOURCE_DATA) * count);
for (int i = 0; i < count; ++i) {
resdata[i].pSysMem = textures[i].data;
resdata[i].SysMemPitch = textures[0].width * 4;
resdata[i].SysMemSlicePitch = 0;
}
array->impl.texture = NULL;
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &desc, resdata, &array->impl.texture));
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateShaderResourceView(dx_ctx.device, (ID3D11Resource *)array->impl.texture, NULL, &array->impl.view));
}
void kinc_g4_texture_array_destroy(kinc_g4_texture_array_t *array) {}
void kinc_internal_texture_array_set(kinc_g4_texture_array_t *array, kinc_g4_texture_unit_t unit) {
if (unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] < 0)
return;
dx_ctx.context->lpVtbl->PSSetShaderResources(dx_ctx.context, unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], 1, &array->impl.view);
// this->stage = unit.unit;
// setTextures[stage] = this;
}

View File

@ -0,0 +1,18 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
struct ID3D11Texture2D;
struct ID3D11ShaderResourceView;
typedef struct {
struct ID3D11Texture2D *texture;
struct ID3D11ShaderResourceView *view;
// void set(Kore::Graphics4::TextureUnit unit);
} kinc_g4_texture_array_impl_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,95 @@
#include <kinc/graphics4/vertexbuffer.h>
void kinc_g4_vertex_buffer_init(kinc_g4_vertex_buffer_t *buffer, int count, kinc_g4_vertex_structure_t *structure, kinc_g4_usage_t usage,
int instance_data_step_rate) {
buffer->impl.count = count;
buffer->impl.stride = 0;
for (int i = 0; i < structure->size; ++i) {
buffer->impl.stride += kinc_g4_vertex_data_size(structure->elements[i].data);
}
if (usage == KINC_G4_USAGE_DYNAMIC) {
buffer->impl.vertices = NULL;
}
else {
buffer->impl.vertices = (float *)malloc(buffer->impl.stride * count);
}
D3D11_BUFFER_DESC bufferDesc;
bufferDesc.CPUAccessFlags = 0;
buffer->impl.usage = usage;
switch (usage) {
case KINC_G4_USAGE_STATIC:
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
break;
case KINC_G4_USAGE_DYNAMIC:
bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
break;
case KINC_G4_USAGE_READABLE:
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
break;
}
bufferDesc.ByteWidth = buffer->impl.stride * count;
bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bufferDesc.MiscFlags = 0;
bufferDesc.StructureByteStride = 0;
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateBuffer(dx_ctx.device, &bufferDesc, NULL, &buffer->impl.vb));
}
void kinc_g4_vertex_buffer_destroy(kinc_g4_vertex_buffer_t *buffer) {
buffer->impl.vb->lpVtbl->Release(buffer->impl.vb);
free(buffer->impl.vertices);
buffer->impl.vertices = NULL;
}
float *kinc_g4_vertex_buffer_lock_all(kinc_g4_vertex_buffer_t *buffer) {
return kinc_g4_vertex_buffer_lock(buffer, 0, buffer->impl.count);
}
float *kinc_g4_vertex_buffer_lock(kinc_g4_vertex_buffer_t *buffer, int start, int count) {
buffer->impl.lockStart = start;
buffer->impl.lockCount = count;
if (buffer->impl.usage == KINC_G4_USAGE_DYNAMIC) {
D3D11_MAPPED_SUBRESOURCE mappedResource;
memset(&mappedResource, 0, sizeof(D3D11_MAPPED_SUBRESOURCE));
dx_ctx.context->lpVtbl->Map(dx_ctx.context, (ID3D11Resource *)buffer->impl.vb, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
float *data = (float *)mappedResource.pData;
return &data[start * buffer->impl.stride / 4];
}
else {
return &buffer->impl.vertices[start * buffer->impl.stride / 4];
}
}
void kinc_g4_vertex_buffer_unlock_all(kinc_g4_vertex_buffer_t *buffer) {
kinc_g4_vertex_buffer_unlock(buffer, buffer->impl.lockCount);
}
void kinc_g4_vertex_buffer_unlock(kinc_g4_vertex_buffer_t *buffer, int count) {
if (buffer->impl.usage == KINC_G4_USAGE_DYNAMIC) {
dx_ctx.context->lpVtbl->Unmap(dx_ctx.context, (ID3D11Resource *)buffer->impl.vb, 0);
}
else {
dx_ctx.context->lpVtbl->UpdateSubresource(dx_ctx.context, (ID3D11Resource *)buffer->impl.vb, 0, NULL, buffer->impl.vertices, 0, 0);
}
}
int kinc_internal_g4_vertex_buffer_set(kinc_g4_vertex_buffer_t *buffer, int offset) {
// UINT stride = myStride;
// UINT internaloffset = 0;
// dx_ctx.context->IASetVertexBuffers(0, 1, &vb, &stride, &internaloffset);
return 0;
}
int kinc_g4_vertex_buffer_count(kinc_g4_vertex_buffer_t *buffer) {
return buffer->impl.count;
}
int kinc_g4_vertex_buffer_stride(kinc_g4_vertex_buffer_t *buffer) {
return buffer->impl.stride;
}

View File

@ -0,0 +1,13 @@
#pragma once
struct ID3D11Buffer;
typedef struct {
struct ID3D11Buffer *vb;
int stride;
int count;
int lockStart;
int lockCount;
float *vertices;
int usage;
} kinc_g4_vertex_buffer_impl_t;

View File

@ -0,0 +1,66 @@
#include <Kinc/Compute/Compute.h>
#include <Kinc/Graphics4/RenderTarget.h>
#include <Kinc/Graphics4/Texture.h>
#include <Kinc/Math/Core.h>
void kinc_compute_shader_init(kinc_compute_shader_t *shader, void *source, int length) {}
void kinc_compute_shader_destroy(kinc_compute_shader_t *shader) {}
kinc_compute_constant_location_t kinc_compute_shader_get_constant_location(kinc_compute_shader_t *shader, const char *name) {
kinc_compute_constant_location_t location = {0};
return location;
}
kinc_compute_texture_unit_t kinc_compute_shader_get_texture_unit(kinc_compute_shader_t *shader, const char *name) {
kinc_compute_texture_unit_t unit = {0};
return unit;
}
void kinc_compute_set_bool(kinc_compute_constant_location_t location, bool value) {}
void kinc_compute_set_int(kinc_compute_constant_location_t location, int value) {}
void kinc_compute_set_float(kinc_compute_constant_location_t location, float value) {}
void kinc_compute_set_float2(kinc_compute_constant_location_t location, float value1, float value2) {}
void kinc_compute_set_float3(kinc_compute_constant_location_t location, float value1, float value2, float value3) {}
void kinc_compute_set_float4(kinc_compute_constant_location_t location, float value1, float value2, float value3, float value4) {}
void kinc_compute_set_floats(kinc_compute_constant_location_t location, float *values, int count) {}
void kinc_compute_set_matrix4(kinc_compute_constant_location_t location, kinc_matrix4x4_t *value) {}
void kinc_compute_set_matrix3(kinc_compute_constant_location_t location, kinc_matrix3x3_t *value) {}
void kinc_compute_set_texture(kinc_compute_texture_unit_t unit, kinc_g4_texture_t *texture, kinc_compute_access_t access) {}
void kinc_compute_set_render_target(kinc_compute_texture_unit_t unit, kinc_g4_render_target_t *target, kinc_compute_access_t access) {}
void kinc_compute_set_sampled_texture(kinc_compute_texture_unit_t unit, kinc_g4_texture_t *texture) {}
void kinc_compute_set_sampled_render_target(kinc_compute_texture_unit_t unit, kinc_g4_render_target_t *target) {}
void kinc_compute_set_sampled_depth_from_render_target(kinc_compute_texture_unit_t unit, kinc_g4_render_target_t *target) {}
void kinc_compute_set_texture_addressing(kinc_compute_texture_unit_t unit, kinc_g4_texture_direction_t dir, kinc_g4_texture_addressing_t addressing) {}
void kinc_compute_set_texture3d_addressing(kinc_compute_texture_unit_t unit, kinc_g4_texture_direction_t dir, kinc_g4_texture_addressing_t addressing) {}
void kinc_compute_set_texture_magnification_filter(kinc_compute_texture_unit_t unit, kinc_g4_texture_filter_t filter) {}
void kinc_compute_set_texture3d_magnification_filter(kinc_compute_texture_unit_t unit, kinc_g4_texture_filter_t filter) {}
void kinc_compute_set_texture_minification_filter(kinc_compute_texture_unit_t unit, kinc_g4_texture_filter_t filter) {}
void kinc_compute_set_texture3d_minification_filter(kinc_compute_texture_unit_t unit, kinc_g4_texture_filter_t filter) {}
void kinc_compute_set_texture_mipmap_filter(kinc_compute_texture_unit_t unit, kinc_g4_mipmap_filter_t filter) {}
void kinc_compute_set_texture3d_mipmap_filter(kinc_compute_texture_unit_t unit, kinc_g4_mipmap_filter_t filter) {}
void kinc_compute_set_shader(kinc_compute_shader_t *shader) {}
void kinc_compute(int x, int y, int z) {}

View File

@ -0,0 +1,25 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
int nothing;
} kinc_compute_constant_location_impl_t;
typedef struct {
int nothing;
} kinc_compute_texture_unit_impl_t;
typedef struct {
int nothing;
} kinc_compute_internal_shader_constant_t;
typedef struct {
int nothing;
} kinc_compute_shader_impl_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,841 @@
#include <kinc/display.h>
#include <kinc/graphics4/graphics.h>
#include <kinc/graphics4/indexbuffer.h>
#include <kinc/graphics4/pipeline.h>
#include <kinc/graphics4/shader.h>
#include <kinc/graphics4/texture.h>
#include <kinc/graphics4/vertexbuffer.h>
#include <kinc/math/core.h>
#undef CreateWindow
#include <kinc/system.h>
#include <kinc/window.h>
#include <kinc/backend/SystemMicrosoft.h>
#include <kinc/backend/Windows.h>
#include <kinc/log.h>
#include <vector>
#include "Direct3D9.h"
LPDIRECT3D9 d3d;
LPDIRECT3DDEVICE9 device;
namespace {
HWND hWnd;
int _width;
int _height;
unsigned hz;
bool vsync;
bool resizable;
D3DVIEWPORT9 vp;
bool swapBuffers() {
HRESULT result;
if (resizable) {
RECT vRect;
GetClientRect(hWnd, &vRect);
result = device->Present(&vRect, &vRect, 0, 0);
}
else {
result = device->Present(0, 0, 0, 0);
}
return result != D3DERR_DEVICELOST;
}
kinc_g4_shader_t *pixelShader = nullptr;
kinc_g4_shader_t *vertexShader = nullptr;
IDirect3DSurface9 *backBuffer = nullptr;
IDirect3DSurface9 *depthBuffer = nullptr;
void initDeviceStates() {
D3DCAPS9 caps;
device->GetDeviceCaps(&caps);
device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
// device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
#ifndef USE_SHADER
device->SetRenderState(D3DRS_LIGHTING, FALSE);
#endif
device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
#ifndef USE_SHADER
device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT);
kinc_microsoft_affirm(device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE));
kinc_microsoft_affirm(device->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE));
#endif
// if (d3dpp.Windowed != TRUE) Cursor->Hide();
device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
for (int i = 0; i < 16; ++i) {
device->SetSamplerState(i, D3DSAMP_MAGFILTER, D3DTEXF_ANISOTROPIC);
device->SetSamplerState(i, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC);
device->SetSamplerState(i, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
device->SetSamplerState(i, D3DSAMP_MAXANISOTROPY, caps.MaxAnisotropy);
}
device->SetSamplerState(D3DVERTEXTEXTURESAMPLER0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
device->SetSamplerState(D3DVERTEXTEXTURESAMPLER0, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC);
device->SetRenderState(D3DRS_ZENABLE, FALSE);
device->Clear(0, 0, D3DCLEAR_TARGET, 0, 0, 0);
}
}
void kinc_g4_internal_destroy_window(int window) {}
void kinc_g4_internal_destroy() {}
extern "C" void kinc_internal_resize(int width, int height) {
if (!resizable) {
return;
}
_width = width;
_height = height;
kinc_g4_viewport(0, 0, width, height);
/*D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = (!fullscreen) ? TRUE : FALSE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferCount = 2;
d3dpp.BackBufferWidth = width;
d3dpp.BackBufferHeight = height;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D24X8;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE; //D3DPRESENT_INTERVAL_IMMEDIATE;
if (antialiasing()) {
if (SUCCEEDED(d3d->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_A8R8G8B8, FALSE, D3DMULTISAMPLE_4_SAMPLES, nullptr)))
d3dpp.MultiSampleType = D3DMULTISAMPLE_4_SAMPLES;
if (SUCCEEDED(d3d->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_A8R8G8B8, FALSE, D3DMULTISAMPLE_8_SAMPLES, nullptr)))
d3dpp.MultiSampleType = D3DMULTISAMPLE_8_SAMPLES;
}
else {
d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
}
device->Reset(&d3dpp);
initDeviceStates();*/
}
extern "C" void kinc_internal_change_framebuffer(int window, struct kinc_framebuffer_options *frame) {}
void kinc_g4_internal_init() {}
void kinc_g4_internal_init_window(int windowId, int depthBufferBits, int stencilBufferBits, bool vsync) {
bool fullscreen = kinc_window_get_mode(windowId) == KINC_WINDOW_MODE_FULLSCREEN || kinc_window_get_mode(windowId) == KINC_WINDOW_MODE_EXCLUSIVE_FULLSCREEN;
d3d = Direct3DCreate9(D3D_SDK_VERSION);
hWnd = kinc_windows_window_handle(windowId);
long style = GetWindowLong(hWnd, GWL_STYLE);
resizable = false;
if ((style & WS_SIZEBOX) != 0) {
resizable = true;
}
if ((style & WS_MAXIMIZEBOX) != 0) {
resizable = true;
}
// TODO (DK) just setup the primary window for now and ignore secondaries
// -this should probably be implemented via swap chain for real at a later time
// -http://www.mvps.org/directx/articles/rendering_to_multiple_windows.htm
if (windowId > 0) {
return;
}
#ifdef KORE_WINDOWS
// TODO (DK) convert depthBufferBits + stencilBufferBits to: d3dpp.AutoDepthStencilFormat = D3DFMT_D24X8;
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = (!fullscreen) ? TRUE : FALSE;
if (resizable) {
d3dpp.SwapEffect = D3DSWAPEFFECT_COPY;
d3dpp.BackBufferCount = 1;
kinc_display_mode_t mode = kinc_display_current_mode(kinc_primary_display());
d3dpp.BackBufferWidth = mode.width;
d3dpp.BackBufferHeight = mode.height;
}
else {
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferCount = 2;
d3dpp.BackBufferWidth = kinc_window_width(windowId);
d3dpp.BackBufferHeight = kinc_window_height(windowId);
}
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D24X8;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
// d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
if (kinc_g4_antialiasing_samples() > 1) {
for (int samples = min(kinc_g4_antialiasing_samples(), 16); samples > 1; --samples) {
if (SUCCEEDED(d3d->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_A8R8G8B8, FALSE, (D3DMULTISAMPLE_TYPE)samples, nullptr))) {
d3dpp.MultiSampleType = (D3DMULTISAMPLE_TYPE)samples;
break;
}
}
}
#endif
if (!SUCCEEDED(d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &device)))
d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device);
// d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device);
#ifdef KORE_WINDOWS
// if (System::hasShowWindowFlag(/*windowId*/)) {
ShowWindow(hWnd, SW_SHOWDEFAULT);
UpdateWindow(hWnd);
//}
#endif
initDeviceStates();
#ifdef KORE_WINDOWS
if (fullscreen) {
// hz = d3dpp.FullScreen_RefreshRateInHz;
D3DDISPLAYMODE mode;
device->GetDisplayMode(0, &mode);
hz = mode.RefreshRate;
}
if (!fullscreen || hz == 0) {
DEVMODE devMode;
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devMode);
hz = devMode.dmDisplayFrequency;
}
#endif
// vsync = d3dpp.PresentationInterval != D3DPRESENT_INTERVAL_IMMEDIATE;
kinc_ticks_t test1 = kinc_timestamp();
for (int i = 0; i < 3; ++i) {
kinc_g4_swap_buffers();
}
kinc_ticks_t test2 = kinc_timestamp();
if (test2 - test1 < (1.0 / hz) * kinc_frequency()) {
vsync = false;
}
else {
vsync = true;
}
_width = kinc_window_width(windowId);
_height = kinc_window_height(windowId);
}
void kinc_g4_flush() {}
namespace {
DWORD convertFilter(kinc_g4_texture_filter_t filter) {
switch (filter) {
case KINC_G4_TEXTURE_FILTER_POINT:
return D3DTEXF_POINT;
case KINC_G4_TEXTURE_FILTER_LINEAR:
return D3DTEXF_LINEAR;
case KINC_G4_TEXTURE_FILTER_ANISOTROPIC:
return D3DTEXF_ANISOTROPIC;
default:
return D3DTEXF_POINT;
}
}
DWORD convertMipFilter(kinc_g4_mipmap_filter_t filter) {
switch (filter) {
case KINC_G4_MIPMAP_FILTER_NONE:
return D3DTEXF_NONE;
case KINC_G4_MIPMAP_FILTER_POINT:
return D3DTEXF_POINT;
case KINC_G4_MIPMAP_FILTER_LINEAR:
return D3DTEXF_LINEAR;
default:
return D3DTEXF_NONE;
}
}
}
void kinc_g4_set_texture_magnification_filter(kinc_g4_texture_unit_t texunit, kinc_g4_texture_filter_t filter) {
device->SetSamplerState(texunit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], D3DSAMP_MAGFILTER, convertFilter(filter));
}
void kinc_g4_set_texture3d_magnification_filter(kinc_g4_texture_unit_t texunit, kinc_g4_texture_filter_t filter) {
kinc_g4_set_texture_magnification_filter(texunit, filter);
}
void kinc_g4_set_texture_minification_filter(kinc_g4_texture_unit_t texunit, kinc_g4_texture_filter_t filter) {
device->SetSamplerState(texunit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], D3DSAMP_MINFILTER, convertFilter(filter));
}
void kinc_g4_set_texture3d_minification_filter(kinc_g4_texture_unit_t texunit, kinc_g4_texture_filter_t filter) {
kinc_g4_set_texture_minification_filter(texunit, filter);
}
void kinc_g4_set_texture_mipmap_filter(kinc_g4_texture_unit_t texunit, kinc_g4_mipmap_filter_t filter) {
device->SetSamplerState(texunit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], D3DSAMP_MIPFILTER, convertMipFilter(filter));
}
void kinc_g4_set_texture3d_mipmap_filter(kinc_g4_texture_unit_t texunit, kinc_g4_mipmap_filter_t filter) {
kinc_g4_set_texture_mipmap_filter(texunit, filter);
}
void kinc_g4_set_texture_compare_mode(kinc_g4_texture_unit_t unit, bool enabled) {}
void kinc_g4_set_texture_compare_func(kinc_g4_texture_unit_t unit, kinc_g4_compare_mode_t mode) {}
void kinc_g4_set_cubemap_compare_mode(kinc_g4_texture_unit_t unit, bool enabled) {}
void kinc_g4_set_cubemap_compare_func(kinc_g4_texture_unit_t unit, kinc_g4_compare_mode_t mode) {}
void kinc_g4_set_texture_max_anisotropy(kinc_g4_texture_unit_t unit, uint16_t max_anisotropy) {
device->SetSamplerState(unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], D3DSAMP_MAXANISOTROPY, max_anisotropy);
}
void kinc_g4_set_cubemap_max_anisotropy(kinc_g4_texture_unit_t unit, uint16_t max_anisotropy) {}
void kinc_g4_set_texture_lod(kinc_g4_texture_unit_t unit, float lod_min_clamp, float lod_max_clamp) {
// device->SetSamplerState(unit.impl.unit, D3DSAMP_, );
}
void kinc_g4_set_cubemap_lod(kinc_g4_texture_unit_t unit, float lod_min_clamp, float lod_max_clamp) {}
void kinc_g4_set_render_targets(struct kinc_g4_render_target **targets, int count) {
// if (backBuffer != nullptr) backBuffer->Release();
if (backBuffer == nullptr) {
device->GetRenderTarget(0, &backBuffer);
device->GetDepthStencilSurface(&depthBuffer);
}
kinc_microsoft_affirm(device->SetDepthStencilSurface(targets[0]->impl.depthSurface));
for (int i = 0; i < count; ++i) {
kinc_microsoft_affirm(device->SetRenderTarget(i, targets[i]->impl.colorSurface));
}
}
void kinc_g4_set_render_target_face(struct kinc_g4_render_target *texture, int face) {}
int kinc_g4_max_bound_textures(void) {
return 8;
}
// void Graphics::setDepthStencilTarget(Texture* texture) {
// //if (depthBuffer != nullptr) depthBuffer->Release();
// device->GetDepthStencilSurface(&depthBuffer);
// Microsoft::affirm(device->SetDepthStencilSurface(dcast<D3D9Texture*>(texture)->getSurface()));
//}
void kinc_g4_restore_render_target() {
if (backBuffer != nullptr) {
device->SetRenderTarget(0, backBuffer);
device->SetRenderTarget(1, nullptr);
backBuffer->Release();
backBuffer = nullptr;
device->SetDepthStencilSurface(depthBuffer);
depthBuffer->Release();
depthBuffer = nullptr;
kinc_g4_viewport(0, 0, _width, _height);
}
}
void kinc_g4_draw_indexed_vertices() {
device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, kinc_g4_vertex_buffer_count(kinc_internal_current_vertex_buffer), 0,
kinc_g4_index_buffer_count(kinc_internal_current_index_buffer) / 3);
}
void kinc_g4_draw_indexed_vertices_from_to(int start, int count) {
device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, kinc_g4_vertex_buffer_count(kinc_internal_current_vertex_buffer), start, count / 3);
}
void kinc_g4_draw_indexed_vertices_from_to_from(int start, int count, int vertex_offset) {
device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, vertex_offset, 0, kinc_g4_vertex_buffer_count(kinc_internal_current_vertex_buffer), start, count / 3);
}
void kinc_g4_draw_indexed_vertices_instanced(int instanceCount) {
kinc_microsoft_affirm(device->SetStreamSourceFreq(kinc_internal_current_vertex_buffer->impl._offset, (D3DSTREAMSOURCE_INDEXEDDATA | instanceCount)));
device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, kinc_g4_vertex_buffer_count(kinc_internal_current_vertex_buffer), 0,
kinc_g4_index_buffer_count(kinc_internal_current_index_buffer) / 3);
}
void kinc_g4_draw_indexed_vertices_instanced_from_to(int instanceCount, int start, int count) {
kinc_microsoft_affirm(device->SetStreamSourceFreq(kinc_internal_current_vertex_buffer->impl._offset, (D3DSTREAMSOURCE_INDEXEDDATA | instanceCount)));
device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, kinc_g4_vertex_buffer_count(kinc_internal_current_vertex_buffer), start, count / 3);
}
void kinc_g4_set_texture_addressing(kinc_g4_texture_unit_t unit, kinc_g4_texture_direction_t dir, kinc_g4_texture_addressing_t addressing) {
DWORD value = 0;
switch (addressing) {
case KINC_G4_TEXTURE_ADDRESSING_REPEAT:
value = D3DTADDRESS_WRAP;
break;
case KINC_G4_TEXTURE_ADDRESSING_MIRROR:
value = D3DTADDRESS_MIRROR;
break;
case KINC_G4_TEXTURE_ADDRESSING_CLAMP:
value = D3DTADDRESS_CLAMP;
break;
case KINC_G4_TEXTURE_ADDRESSING_BORDER:
value = D3DTADDRESS_BORDER;
break;
}
device->SetSamplerState(unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], dir == KINC_G4_TEXTURE_DIRECTION_U ? D3DSAMP_ADDRESSU : D3DSAMP_ADDRESSV, value);
}
void kinc_g4_set_texture3d_addressing(kinc_g4_texture_unit_t unit, kinc_g4_texture_direction_t dir, kinc_g4_texture_addressing_t addressing) {
kinc_g4_set_texture_addressing(unit, dir, addressing);
}
namespace {
void tod3dmatrix(kinc_matrix4x4_t *matrix, D3DMATRIX &d3dm) {
d3dm._11 = kinc_matrix4x4_get(matrix, 0, 0);
d3dm._12 = kinc_matrix4x4_get(matrix, 0, 1);
d3dm._13 = kinc_matrix4x4_get(matrix, 0, 2);
d3dm._14 = kinc_matrix4x4_get(matrix, 0, 3);
d3dm._21 = kinc_matrix4x4_get(matrix, 1, 0);
d3dm._22 = kinc_matrix4x4_get(matrix, 1, 1);
d3dm._23 = kinc_matrix4x4_get(matrix, 1, 2);
d3dm._24 = kinc_matrix4x4_get(matrix, 1, 3);
d3dm._31 = kinc_matrix4x4_get(matrix, 2, 0);
d3dm._32 = kinc_matrix4x4_get(matrix, 2, 1);
d3dm._33 = kinc_matrix4x4_get(matrix, 2, 2);
d3dm._34 = kinc_matrix4x4_get(matrix, 2, 3);
d3dm._41 = kinc_matrix4x4_get(matrix, 3, 0);
d3dm._42 = kinc_matrix4x4_get(matrix, 3, 1);
d3dm._43 = kinc_matrix4x4_get(matrix, 3, 2);
d3dm._44 = kinc_matrix4x4_get(matrix, 3, 3);
}
}
void kinc_g4_clear(unsigned flags, unsigned color, float depth, int stencil) {
device->Clear(0, nullptr, flags, color, depth, stencil);
}
void kinc_g4_begin(int window) {
// TODO (DK) ignore secondary windows for now
if (window > 0) {
return;
}
kinc_g4_viewport(0, 0, _width, _height);
device->BeginScene();
}
void kinc_g4_viewport(int x, int y, int width, int height) {
vp.X = x;
vp.Y = y;
vp.Width = width;
vp.Height = height;
device->SetViewport(&vp);
}
void kinc_g4_scissor(int x, int y, int width, int height) {
device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
RECT rc;
rc.left = x;
rc.top = y;
rc.right = x + width;
rc.bottom = y + height;
device->SetScissorRect(&rc);
}
void kinc_g4_disable_scissor() {
device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
}
void kinc_g4_end(int window) {
// TODO (DK) ignore secondary windows for now
if (window > 0) {
return;
}
/*if (backBuffer != nullptr) {
backBuffer->Release();
backBuffer = nullptr;
}*/
device->EndScene();
}
bool kinc_window_vsynced(int window) {
return vsync;
}
// unsigned Graphics4::refreshRate() {
// return hz;
//}
bool kinc_g4_swap_buffers() {
return ::swapBuffers();
}
void kinc_g4_set_stencil_reference_value(int value) {}
void kinc_g4_set_blend_constant(float r, float g, float b, float a) {
device->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA((int)(r * 255), (int)(g * 255), (int)(b * 255), (int)(a * 255)));
}
void kinc_g4_set_bool(kinc_g4_constant_location_t position, bool value) {
if (position.impl.shaderType == -1)
return;
BOOL bools[4];
bools[0] = value ? 1 : 0;
bools[1] = bools[0];
bools[2] = bools[0];
bools[3] = bools[0];
if (position.impl.shaderType == 0)
device->SetVertexShaderConstantB(position.impl.reg.regindex, &bools[0], 1);
else
device->SetPixelShaderConstantB(position.impl.reg.regindex, &bools[0], 1);
}
void kinc_g4_set_int(kinc_g4_constant_location_t position, int value) {
if (position.impl.shaderType == -1)
return;
if (position.impl.reg.regtype == 'f') {
kinc_g4_set_float(position, (float)value);
}
else {
int ints[4];
ints[0] = value;
ints[1] = value;
ints[2] = value;
ints[3] = value;
if (position.impl.shaderType == 0)
device->SetVertexShaderConstantI(position.impl.reg.regindex, &ints[0], 1);
else
device->SetPixelShaderConstantI(position.impl.reg.regindex, &ints[0], 1);
}
}
void kinc_g4_set_int2(kinc_g4_constant_location_t position, int value1, int value2) {
if (position.impl.shaderType == -1)
return;
if (position.impl.reg.regtype == 'f') {
kinc_g4_set_float2(position, (float)value1, (float)value2);
}
else {
int ints[4];
ints[0] = value1;
ints[1] = value2;
ints[2] = value1;
ints[3] = value2;
if (position.impl.shaderType == 0)
device->SetVertexShaderConstantI(position.impl.reg.regindex, &ints[0], 1);
else
device->SetPixelShaderConstantI(position.impl.reg.regindex, &ints[0], 1);
}
}
void kinc_g4_set_int3(kinc_g4_constant_location_t position, int value1, int value2, int value3) {
if (position.impl.shaderType == -1)
return;
if (position.impl.reg.regtype == 'f') {
kinc_g4_set_float3(position, (float)value1, (float)value2, (float)value3);
}
else {
int ints[4];
ints[0] = value1;
ints[1] = value2;
ints[2] = value3;
ints[3] = value1;
if (position.impl.shaderType == 0)
device->SetVertexShaderConstantI(position.impl.reg.regindex, &ints[0], 1);
else
device->SetPixelShaderConstantI(position.impl.reg.regindex, &ints[0], 1);
}
}
void kinc_g4_set_int4(kinc_g4_constant_location_t position, int value1, int value2, int value3, int value4) {
if (position.impl.shaderType == -1)
return;
if (position.impl.reg.regtype == 'f') {
kinc_g4_set_float4(position, (float)value1, (float)value2, (float)value3, (float)value4);
}
else {
int ints[4];
ints[0] = value1;
ints[1] = value2;
ints[2] = value3;
ints[3] = value4;
if (position.impl.shaderType == 0)
device->SetVertexShaderConstantI(position.impl.reg.regindex, &ints[0], 1);
else
device->SetPixelShaderConstantI(position.impl.reg.regindex, &ints[0], 1);
}
}
void kinc_g4_set_ints(kinc_g4_constant_location_t location, int *values, int count) {
if (location.impl.shaderType == -1)
return;
int registerCount = (count + 3) / 4; // round up
if (registerCount == count / 4) { // round down
if (location.impl.shaderType == 0)
device->SetVertexShaderConstantI(location.impl.reg.regindex, values, registerCount);
else
device->SetPixelShaderConstantI(location.impl.reg.regindex, values, registerCount);
}
else {
int *data = (int *)alloca(registerCount * 4 * sizeof(int));
memcpy(data, values, count * sizeof(int));
if (location.impl.shaderType == 0)
device->SetVertexShaderConstantI(location.impl.reg.regindex, data, registerCount);
else
device->SetPixelShaderConstantI(location.impl.reg.regindex, data, registerCount);
}
}
void kinc_g4_set_float(kinc_g4_constant_location_t position, float value) {
if (position.impl.shaderType == -1)
return;
float floats[4];
floats[0] = value;
floats[1] = value;
floats[2] = value;
floats[3] = value;
if (position.impl.shaderType == 0)
device->SetVertexShaderConstantF(position.impl.reg.regindex, floats, 1);
else
device->SetPixelShaderConstantF(position.impl.reg.regindex, floats, 1);
}
void kinc_g4_set_float2(kinc_g4_constant_location_t position, float value1, float value2) {
if (position.impl.shaderType == -1)
return;
float floats[4];
floats[0] = value1;
floats[1] = value2;
floats[2] = value1;
floats[3] = value2;
if (position.impl.shaderType == 0)
device->SetVertexShaderConstantF(position.impl.reg.regindex, floats, 1);
else
device->SetPixelShaderConstantF(position.impl.reg.regindex, floats, 1);
}
void kinc_g4_set_float3(kinc_g4_constant_location_t position, float value1, float value2, float value3) {
if (position.impl.shaderType == -1)
return;
float floats[4];
floats[0] = value1;
floats[1] = value2;
floats[2] = value3;
floats[3] = value1;
if (position.impl.shaderType == 0)
device->SetVertexShaderConstantF(position.impl.reg.regindex, floats, 1);
else
device->SetPixelShaderConstantF(position.impl.reg.regindex, floats, 1);
}
void kinc_g4_set_float4(kinc_g4_constant_location_t position, float value1, float value2, float value3, float value4) {
if (position.impl.shaderType == -1)
return;
float floats[4];
floats[0] = value1;
floats[1] = value2;
floats[2] = value3;
floats[3] = value4;
if (position.impl.shaderType == 0)
device->SetVertexShaderConstantF(position.impl.reg.regindex, floats, 1);
else
device->SetPixelShaderConstantF(position.impl.reg.regindex, floats, 1);
}
void kinc_g4_set_floats(kinc_g4_constant_location_t location, float *values, int count) {
if (location.impl.shaderType == -1)
return;
int registerCount = (count + 3) / 4; // round up
if (registerCount == count / 4) { // round down
if (location.impl.shaderType == 0)
device->SetVertexShaderConstantF(location.impl.reg.regindex, values, registerCount);
else
device->SetPixelShaderConstantF(location.impl.reg.regindex, values, registerCount);
}
else {
float *data = (float *)alloca(registerCount * 4 * sizeof(float));
memcpy(data, values, count * sizeof(float));
if (location.impl.shaderType == 0)
device->SetVertexShaderConstantF(location.impl.reg.regindex, data, registerCount);
else
device->SetPixelShaderConstantF(location.impl.reg.regindex, data, registerCount);
}
}
void kinc_g4_set_matrix4(kinc_g4_constant_location_t location, kinc_matrix4x4_t *value) {
if (location.impl.shaderType == -1)
return;
float floats[16];
for (int y = 0; y < 4; ++y) {
for (int x = 0; x < 4; ++x) {
floats[y * 4 + x] = kinc_matrix4x4_get(value, y, x);
}
}
if (location.impl.shaderType == 0)
device->SetVertexShaderConstantF(location.impl.reg.regindex, floats, 4);
else
device->SetPixelShaderConstantF(location.impl.reg.regindex, floats, 4);
}
void kinc_g4_set_matrix3(kinc_g4_constant_location_t location, kinc_matrix3x3_t *value) {
if (location.impl.shaderType == -1)
return;
float floats[12];
for (int y = 0; y < 3; ++y) {
for (int x = 0; x < 3; ++x) {
floats[y * 4 + x] = kinc_matrix3x3_get(value, y, x);
}
}
if (location.impl.shaderType == 0)
device->SetVertexShaderConstantF(location.impl.reg.regindex, floats, 3);
else
device->SetPixelShaderConstantF(location.impl.reg.regindex, floats, 3);
}
void kinc_g4_set_vertex_buffers(kinc_g4_vertex_buffer_t **buffers, int count) {
for (int i = 0; i < count; ++i) {
kinc_internal_g4_vertex_buffer_set(buffers[i], i);
}
}
void kinc_g4_set_index_buffer(kinc_g4_index_buffer_t *buffer) {
kinc_internal_g4_index_buffer_set(buffer);
}
#ifdef KINC_KONG
void kinc_internal_texture_set(kinc_g4_texture_t *texture, uint32_t unit);
void kinc_g4_set_texture(uint32_t unit, struct kinc_g4_texture *texture) {
kinc_internal_texture_set(texture, unit);
}
#else
void kinc_internal_texture_set(kinc_g4_texture_t *texture, kinc_g4_texture_unit_t unit);
void kinc_g4_set_texture(kinc_g4_texture_unit_t unit, struct kinc_g4_texture *texture) {
kinc_internal_texture_set(texture, unit);
}
#endif
void kinc_g4_set_image_texture(kinc_g4_texture_unit_t unit, struct kinc_g4_texture *texture) {}
unsigned queryCount = 0;
std::vector<IDirect3DQuery9 *> queryPool;
bool kinc_g4_init_occlusion_query(unsigned *occlusionQuery) {
// check if the runtime supports queries
HRESULT result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, NULL);
if (FAILED(result)) {
kinc_log(KINC_LOG_LEVEL_WARNING, "Internal query creation failed, result: 0x%X.", result);
return false;
}
IDirect3DQuery9 *pQuery = nullptr;
device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &pQuery);
queryPool.push_back(pQuery);
*occlusionQuery = queryCount;
++queryCount;
return true;
}
void kinc_g4_delete_occlusion_query(unsigned occlusionQuery) {
if (occlusionQuery < queryPool.size())
queryPool[occlusionQuery] = nullptr;
}
void kinc_g4_start_occlusion_query(unsigned occlusionQuery) {
IDirect3DQuery9 *pQuery = queryPool[occlusionQuery];
if (pQuery != nullptr) {
pQuery->Issue(D3DISSUE_BEGIN);
}
}
void kinc_g4_end_occlusion_query(unsigned occlusionQuery) {
IDirect3DQuery9 *pQuery = queryPool[occlusionQuery];
if (pQuery != nullptr) {
pQuery->Issue(D3DISSUE_END);
}
}
bool kinc_g4_are_query_results_available(unsigned occlusionQuery) {
IDirect3DQuery9 *pQuery = queryPool[occlusionQuery];
if (pQuery != nullptr) {
if (S_OK == pQuery->GetData(0, 0, 0)) {
return true;
}
}
return false;
}
void kinc_g4_get_query_results(unsigned occlusionQuery, unsigned *pixelCount) {
IDirect3DQuery9 *pQuery = queryPool[occlusionQuery];
if (pQuery != nullptr) {
DWORD numberOfPixelsDrawn;
HRESULT result = pQuery->GetData(&numberOfPixelsDrawn, sizeof(DWORD), 0);
if (S_OK == result) {
*pixelCount = numberOfPixelsDrawn;
}
else {
kinc_log(KINC_LOG_LEVEL_WARNING, "Check first if results are available");
*pixelCount = 0;
}
}
}
void kinc_g4_set_texture_array(kinc_g4_texture_unit_t unit, struct kinc_g4_texture_array *array) {}
void kinc_g4_set_pipeline(struct kinc_g4_pipeline *pipeline) {
kinc_g4_internal_set_pipeline(pipeline);
}
bool kinc_g4_supports_instanced_rendering() {
return true;
}
bool kinc_g4_supports_compute_shaders() {
return false;
}
bool kinc_g4_supports_blend_constants() {
D3DCAPS9 pCaps = {};
if (FAILED(device->GetDeviceCaps(&pCaps))) {
kinc_log(KINC_LOG_LEVEL_ERROR, "Failed to get device caps");
return false;
}
return ((pCaps.SrcBlendCaps & D3DPBLENDCAPS_BLENDFACTOR) != 0) && ((pCaps.DestBlendCaps & D3DPBLENDCAPS_BLENDFACTOR) != 0);
}
bool kinc_g4_supports_non_pow2_textures() {
D3DCAPS9 pCaps = {};
if (FAILED(device->GetDeviceCaps(&pCaps))) {
kinc_log(KINC_LOG_LEVEL_ERROR, "Failed to get device caps");
return false;
}
// only advertise full npot support
return ((pCaps.TextureCaps & D3DPTEXTURECAPS_POW2) == 0) && ((pCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) == 0);
}
bool kinc_g4_render_targets_inverted_y(void) {
return false;
}
void kinc_g4_set_constant_buffer(uint32_t id, struct kinc_g4_constant_buffer *buffer) {}

View File

@ -0,0 +1,12 @@
#pragma once
#include <kinc/graphics4/graphics.h>
#include <kinc/math/matrix.h>
#ifndef NDEBUG
#define D3D_DEBUG_INFO
#endif
#include <d3d9.h>
extern IDirect3D9 *d3d;
extern IDirect3DDevice9 *device;

View File

@ -0,0 +1,34 @@
#ifdef KINC_KONG
#include <kinc/graphics4/constantbuffer.h>
#include "Direct3D9.h"
void kinc_g4_constant_buffer_init(kinc_g4_constant_buffer *buffer, size_t size) {
buffer->impl.size = size;
buffer->impl.last_start = 0;
buffer->impl.last_size = size;
}
void kinc_g4_constant_buffer_destroy(kinc_g4_constant_buffer *buffer) {}
uint8_t *kinc_g4_constant_buffer_lock_all(kinc_g4_constant_buffer *buffer) {
return NULL;
}
uint8_t *kinc_g4_constant_buffer_lock(kinc_g4_constant_buffer *buffer, size_t start, size_t size) {
buffer->impl.last_start = start;
buffer->impl.last_size = size;
return NULL;
}
void kinc_g4_constant_buffer_unlock_all(kinc_g4_constant_buffer *buffer) {}
void kinc_g4_constant_buffer_unlock(kinc_g4_constant_buffer *buffer, size_t count) {}
size_t kinc_g4_constant_buffer_size(kinc_g4_constant_buffer *buffer) {
return buffer->impl.size;
}
#endif

View File

@ -0,0 +1,11 @@
#pragma once
#ifdef KINC_KONG
typedef struct kinc_g4_constant_buffer_impl {
size_t size;
size_t last_start;
size_t last_size;
} kinc_g4_constant_buffer_impl;
#endif

View File

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

View File

@ -0,0 +1,56 @@
#include <kinc/graphics4/graphics.h>
#include <kinc/graphics4/indexbuffer.h>
#include <kinc/backend/SystemMicrosoft.h>
#include "Direct3D9.h"
struct kinc_g4_index_buffer *kinc_internal_current_index_buffer = NULL;
void kinc_g4_index_buffer_init(kinc_g4_index_buffer_t *buffer, int count, kinc_g4_index_buffer_format_t format, kinc_g4_usage_t usage) {
buffer->impl.count = count;
buffer->impl.format = format;
DWORD usageFlags = D3DUSAGE_WRITEONLY;
if (usage == KINC_G4_USAGE_DYNAMIC) {
usageFlags = D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY;
}
kinc_microsoft_affirm(device->CreateIndexBuffer(
sizeof(int) * count, usageFlags, format == KINC_G4_INDEX_BUFFER_FORMAT_32BIT ? D3DFMT_INDEX32 : D3DFMT_INDEX16, D3DPOOL_DEFAULT, &buffer->impl.ib, 0));
}
void kinc_g4_index_buffer_destroy(kinc_g4_index_buffer_t *buffer) {
buffer->impl.ib->Release();
}
static int kinc_g4_internal_index_buffer_stride(kinc_g4_index_buffer_t *buffer) {
return buffer->impl.format == KINC_G4_INDEX_BUFFER_FORMAT_32BIT ? 4 : 2;
}
void *kinc_g4_index_buffer_lock_all(kinc_g4_index_buffer_t *buffer) {
return kinc_g4_index_buffer_lock(buffer, 0, kinc_g4_index_buffer_count(buffer));
}
void *kinc_g4_index_buffer_lock(kinc_g4_index_buffer_t *buffer, int start, int count) {
uint8_t *data;
kinc_microsoft_affirm(buffer->impl.ib->Lock(0, sizeof(int) * kinc_g4_index_buffer_count(buffer), (void **)&data, D3DLOCK_DISCARD));
return &data[start * kinc_g4_internal_index_buffer_stride(buffer)];
}
void kinc_g4_index_buffer_unlock_all(kinc_g4_index_buffer_t *buffer) {
kinc_microsoft_affirm(buffer->impl.ib->Unlock());
}
void kinc_g4_index_buffer_unlock(kinc_g4_index_buffer_t *buffer, int count) {
kinc_g4_index_buffer_unlock_all(buffer);
}
void kinc_internal_g4_index_buffer_set(kinc_g4_index_buffer_t *buffer) {
kinc_internal_current_index_buffer = buffer;
kinc_microsoft_affirm(device->SetIndices(buffer->impl.ib));
}
int kinc_g4_index_buffer_count(kinc_g4_index_buffer_t *buffer) {
return buffer->impl.count;
}

View File

@ -0,0 +1,21 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
struct IDirect3DIndexBuffer9;
typedef struct {
struct IDirect3DIndexBuffer9 *ib;
int count;
int format;
} kinc_g4_index_buffer_impl_t;
struct kinc_g4_index_buffer;
extern struct kinc_g4_index_buffer *kinc_internal_current_index_buffer;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,365 @@
#include <kinc/graphics4/graphics.h>
#include <kinc/graphics4/pipeline.h>
#include <kinc/graphics4/shader.h>
#include <kinc/graphics4/vertexstructure.h>
#include <kinc/log.h>
#include <kinc/system.h>
#include <kinc/backend/SystemMicrosoft.h>
#include "Direct3D9.h"
#include <assert.h>
#include <malloc.h>
namespace {
_D3DBLEND convert_blend_factor(kinc_g4_blending_factor_t factor) {
switch (factor) {
case KINC_G4_BLEND_ONE:
return D3DBLEND_ONE;
case KINC_G4_BLEND_ZERO:
return D3DBLEND_ZERO;
case KINC_G4_BLEND_SOURCE_ALPHA:
return D3DBLEND_SRCALPHA;
case KINC_G4_BLEND_DEST_ALPHA:
return D3DBLEND_DESTALPHA;
case KINC_G4_BLEND_INV_SOURCE_ALPHA:
return D3DBLEND_INVSRCALPHA;
case KINC_G4_BLEND_INV_DEST_ALPHA:
return D3DBLEND_INVDESTALPHA;
case KINC_G4_BLEND_CONSTANT:
return D3DBLEND_BLENDFACTOR;
case KINC_G4_BLEND_INV_CONSTANT:
return D3DBLEND_INVBLENDFACTOR;
default:
assert(false);
return D3DBLEND_SRCALPHA;
}
}
_D3DBLENDOP convert_blend_operation(kinc_g4_blending_operation_t op) {
switch (op) {
case KINC_G4_BLENDOP_ADD:
return D3DBLENDOP_ADD;
case KINC_G4_BLENDOP_SUBTRACT:
return D3DBLENDOP_SUBTRACT;
case KINC_G4_BLENDOP_REVERSE_SUBTRACT:
return D3DBLENDOP_REVSUBTRACT;
case KINC_G4_BLENDOP_MIN:
return D3DBLENDOP_MIN;
case KINC_G4_BLENDOP_MAX:
return D3DBLENDOP_MAX;
default:
assert(false);
return D3DBLENDOP_ADD;
}
}
_D3DCMPFUNC convert(kinc_g4_compare_mode_t mode) {
switch (mode) {
default:
case KINC_G4_COMPARE_ALWAYS:
return D3DCMP_ALWAYS;
case KINC_G4_COMPARE_NEVER:
return D3DCMP_NEVER;
case KINC_G4_COMPARE_EQUAL:
return D3DCMP_EQUAL;
case KINC_G4_COMPARE_NOT_EQUAL:
return D3DCMP_NOTEQUAL;
case KINC_G4_COMPARE_LESS:
return D3DCMP_LESS;
case KINC_G4_COMPARE_LESS_EQUAL:
return D3DCMP_LESSEQUAL;
case KINC_G4_COMPARE_GREATER:
return D3DCMP_GREATER;
case KINC_G4_COMPARE_GREATER_EQUAL:
return D3DCMP_GREATEREQUAL;
}
}
}
void kinc_g4_pipeline_init(kinc_g4_pipeline_t *state) {
memset(state, 0, sizeof(kinc_g4_pipeline));
kinc_g4_internal_pipeline_set_defaults(state);
}
void kinc_g4_pipeline_destroy(kinc_g4_pipeline_t *state) {}
static int find_attribute(struct ShaderAttribute *attributes, const char *name) {
for (int i = 0; i < KINC_INTERNAL_MAX_ATTRIBUTES; ++i) {
if (attributes[i].name == 0) {
return -1;
}
if (strcmp(attributes[i].name, name) == 0) {
return i;
}
}
return -1;
}
static int find_constant(struct ShaderRegister *constants, const char *name) {
for (int i = 0; i < KINC_INTERNAL_MAX_CONSTANTS; ++i) {
if (constants[i].name == 0) {
return -1;
}
if (strcmp(constants[i].name, name) == 0) {
return i;
}
}
return -1;
}
void kinc_g4_pipeline_compile(kinc_g4_pipeline_t *state) {
int highestIndex = 0;
for (int i = 0;; ++i) {
if (state->vertex_shader->impl.attributes[i].name[0] == 0) {
break;
}
int index = state->vertex_shader->impl.attributes[i].index;
if (index > highestIndex) {
highestIndex = index;
}
}
int all = 0;
for (int stream = 0; state->input_layout[stream] != nullptr; ++stream) {
for (int index = 0; index < state->input_layout[stream]->size; ++index) {
if (state->input_layout[stream]->elements[index].data == KINC_G4_VERTEX_DATA_F32_4X4) {
all += 4;
}
else {
all += 1;
}
}
}
D3DVERTEXELEMENT9 *elements = (D3DVERTEXELEMENT9 *)_alloca(sizeof(D3DVERTEXELEMENT9) * (all + 1));
int i = 0;
for (int stream = 0; state->input_layout[stream] != nullptr; ++stream) {
int stride = 0;
for (int index = 0; index < state->input_layout[stream]->size; ++index) {
if (state->input_layout[stream]->elements[index].data != KINC_G4_VERTEX_DATA_F32_4X4) {
elements[i].Stream = stream;
elements[i].Offset = stride;
}
stride += kinc_g4_vertex_data_size(state->input_layout[stream]->elements[index].data);
switch (state->input_layout[stream]->elements[index].data) {
case KINC_G4_VERTEX_DATA_F32_1X:
elements[i].Type = D3DDECLTYPE_FLOAT1;
break;
case KINC_G4_VERTEX_DATA_F32_2X:
elements[i].Type = D3DDECLTYPE_FLOAT2;
break;
case KINC_G4_VERTEX_DATA_F32_3X:
elements[i].Type = D3DDECLTYPE_FLOAT3;
break;
case KINC_G4_VERTEX_DATA_F32_4X:
elements[i].Type = D3DDECLTYPE_FLOAT4;
break;
case KINC_G4_VERTEX_DATA_U8_4X:
elements[i].Type = D3DDECLTYPE_UBYTE4;
break;
case KINC_G4_VERTEX_DATA_U8_4X_NORMALIZED:
elements[i].Type = D3DDECLTYPE_UBYTE4N;
break;
case KINC_G4_VERTEX_DATA_I16_2X:
elements[i].Type = D3DDECLTYPE_SHORT2;
break;
case KINC_G4_VERTEX_DATA_I16_2X_NORMALIZED:
elements[i].Type = D3DDECLTYPE_SHORT2N;
break;
case KINC_G4_VERTEX_DATA_U16_2X_NORMALIZED:
elements[i].Type = D3DDECLTYPE_USHORT2N;
break;
case KINC_G4_VERTEX_DATA_I16_4X:
elements[i].Type = D3DDECLTYPE_SHORT4;
break;
case KINC_G4_VERTEX_DATA_I16_4X_NORMALIZED:
elements[i].Type = D3DDECLTYPE_SHORT4N;
break;
case KINC_G4_VERTEX_DATA_U16_4X_NORMALIZED:
elements[i].Type = D3DDECLTYPE_USHORT4N;
break;
case KINC_G4_VERTEX_DATA_I8_1X:
case KINC_G4_VERTEX_DATA_U8_1X:
case KINC_G4_VERTEX_DATA_I8_1X_NORMALIZED:
case KINC_G4_VERTEX_DATA_U8_1X_NORMALIZED:
case KINC_G4_VERTEX_DATA_I8_2X:
case KINC_G4_VERTEX_DATA_U8_2X:
case KINC_G4_VERTEX_DATA_I8_2X_NORMALIZED:
case KINC_G4_VERTEX_DATA_U8_2X_NORMALIZED:
case KINC_G4_VERTEX_DATA_I8_4X:
case KINC_G4_VERTEX_DATA_I8_4X_NORMALIZED:
case KINC_G4_VERTEX_DATA_I16_1X:
case KINC_G4_VERTEX_DATA_U16_1X:
case KINC_G4_VERTEX_DATA_I16_1X_NORMALIZED:
case KINC_G4_VERTEX_DATA_U16_1X_NORMALIZED:
case KINC_G4_VERTEX_DATA_U16_2X:
case KINC_G4_VERTEX_DATA_U16_4X:
case KINC_G4_VERTEX_DATA_I32_1X:
case KINC_G4_VERTEX_DATA_U32_1X:
case KINC_G4_VERTEX_DATA_I32_2X:
case KINC_G4_VERTEX_DATA_U32_2X:
case KINC_G4_VERTEX_DATA_I32_3X:
case KINC_G4_VERTEX_DATA_U32_3X:
case KINC_G4_VERTEX_DATA_I32_4X:
case KINC_G4_VERTEX_DATA_U32_4X:
elements[i].Type = D3DDECLTYPE_UNUSED;
assert(false);
break;
case KINC_G4_VERTEX_DATA_F32_4X4:
for (int i2 = 0; i2 < 4; ++i2) {
elements[i].Stream = stream;
elements[i].Offset = stride;
elements[i].Type = D3DDECLTYPE_FLOAT4;
elements[i].Method = D3DDECLMETHOD_DEFAULT;
elements[i].Usage = D3DDECLUSAGE_TEXCOORD;
char name[101];
strcpy(name, state->input_layout[stream]->elements[index].name);
strcat(name, "_");
size_t length = strlen(name);
_itoa(i2, &name[length], 10);
name[length + 1] = 0;
int attribute_index = find_attribute(state->vertex_shader->impl.attributes, name);
if (attribute_index < 0) {
kinc_log(KINC_LOG_LEVEL_ERROR, "Could not find attribute %s.", name);
elements[i].UsageIndex = ++highestIndex;
}
else {
elements[i].UsageIndex = state->vertex_shader->impl.attributes[attribute_index].index;
}
++i;
}
break;
}
if (state->input_layout[stream]->elements[index].data != KINC_G4_VERTEX_DATA_F32_4X4) {
elements[i].Method = D3DDECLMETHOD_DEFAULT;
elements[i].Usage = D3DDECLUSAGE_TEXCOORD;
int attribute_index = find_attribute(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name);
if (attribute_index < 0) {
kinc_log(KINC_LOG_LEVEL_ERROR, "Could not find attribute %s.", state->input_layout[stream]->elements[index].name);
elements[i].UsageIndex = ++highestIndex;
}
else {
elements[i].UsageIndex = state->vertex_shader->impl.attributes[attribute_index].index;
}
++i;
}
}
}
elements[all].Stream = 0xff;
elements[all].Offset = 0;
elements[all].Type = D3DDECLTYPE_UNUSED;
elements[all].Method = 0;
elements[all].Usage = 0;
elements[all].UsageIndex = 0;
state->impl.vertexDecleration = nullptr;
kinc_microsoft_affirm(device->CreateVertexDeclaration(elements, &state->impl.vertexDecleration));
int constant_index = find_constant(state->vertex_shader->impl.constants, "gl_HalfPixel");
state->impl.halfPixelLocation = state->vertex_shader->impl.constants[constant_index].regindex;
}
void kinc_g4_internal_set_pipeline(kinc_g4_pipeline_t *pipeline) {
kinc_microsoft_affirm(device->SetVertexShader((IDirect3DVertexShader9 *)pipeline->vertex_shader->impl.shader));
kinc_microsoft_affirm(device->SetPixelShader((IDirect3DPixelShader9 *)pipeline->fragment_shader->impl.shader));
kinc_microsoft_affirm(device->SetVertexDeclaration(pipeline->impl.vertexDecleration));
// TODO (DK) System::screenWidth/Height are only main-window dimensions, what about other windows?
float floats[4];
floats[0] = 1.0f / kinc_width();
floats[1] = 1.0f / kinc_height();
floats[2] = floats[0];
floats[3] = floats[1];
kinc_microsoft_affirm(device->SetVertexShaderConstantF(pipeline->impl.halfPixelLocation, floats, 1));
DWORD flags = 0;
if (pipeline->color_write_mask_red[0]) {
flags |= D3DCOLORWRITEENABLE_RED;
}
if (pipeline->color_write_mask_green[0]) {
flags |= D3DCOLORWRITEENABLE_GREEN;
}
if (pipeline->color_write_mask_blue[0]) {
flags |= D3DCOLORWRITEENABLE_BLUE;
}
if (pipeline->color_write_mask_alpha[0]) {
flags |= D3DCOLORWRITEENABLE_ALPHA;
}
device->SetRenderState(D3DRS_COLORWRITEENABLE, flags);
device->SetRenderState(D3DRS_ALPHABLENDENABLE,
(pipeline->blend_source != KINC_G4_BLEND_ONE || pipeline->blend_destination != KINC_G4_BLEND_ZERO) ? TRUE : FALSE);
device->SetRenderState(D3DRS_SRCBLEND, convert_blend_factor(pipeline->blend_source));
device->SetRenderState(D3DRS_DESTBLEND, convert_blend_factor(pipeline->blend_destination));
device->SetRenderState(D3DRS_BLENDOP, convert_blend_operation(pipeline->blend_operation));
switch (pipeline->cull_mode) {
case KINC_G4_CULL_CLOCKWISE:
device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
break;
case KINC_G4_CULL_COUNTER_CLOCKWISE:
device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
break;
case KINC_G4_CULL_NOTHING:
device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
break;
}
device->SetRenderState(D3DRS_ZENABLE, pipeline->depth_mode != KINC_G4_COMPARE_ALWAYS ? TRUE : FALSE);
device->SetRenderState(D3DRS_ZFUNC, convert(pipeline->depth_mode));
device->SetRenderState(D3DRS_ZWRITEENABLE, pipeline->depth_write ? TRUE : FALSE);
/*
case AlphaTestState:
device->SetRenderState(D3DRS_ALPHATESTENABLE, on ? TRUE : FALSE);
device->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
break;
case AlphaReferenceState:
device->SetRenderState(D3DRS_ALPHAREF, (DWORD)v);
break;
*/
}
kinc_g4_constant_location_t kinc_g4_pipeline_get_constant_location(kinc_g4_pipeline_t *state, const char *name) {
kinc_g4_constant_location_t location;
int fragment_index = find_constant(state->fragment_shader->impl.constants, name);
int vertex_index = find_constant(state->vertex_shader->impl.constants, name);
if (fragment_index >= 0) {
location.impl.reg = state->fragment_shader->impl.constants[fragment_index];
location.impl.shaderType = 1;
}
else if (vertex_index >= 0) {
location.impl.reg = state->vertex_shader->impl.constants[vertex_index];
location.impl.shaderType = 0;
}
else {
location.impl.shaderType = -1;
kinc_log(KINC_LOG_LEVEL_WARNING, "Could not find uniform %s.", name);
}
return location;
}
kinc_g4_texture_unit_t kinc_g4_pipeline_get_texture_unit(kinc_g4_pipeline_t *state, const char *name) {
int fragment_index = find_constant(state->fragment_shader->impl.constants, name);
int vertex_index = find_constant(state->vertex_shader->impl.constants, name);
kinc_g4_texture_unit_t unit;
for (int i = 0; i < KINC_G4_SHADER_TYPE_COUNT; ++i) {
unit.stages[i] = -1;
}
if (fragment_index >= 0) {
unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] = state->fragment_shader->impl.constants[fragment_index].regindex;
}
if (vertex_index >= 0) {
unit.stages[KINC_G4_SHADER_TYPE_VERTEX] = state->vertex_shader->impl.constants[vertex_index].regindex;
}
return unit;
}

View File

@ -0,0 +1,18 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
struct IDirect3DVertexDeclaration9;
typedef struct {
struct IDirect3DVertexDeclaration9 *vertexDecleration;
int halfPixelLocation;
} kinc_g4_pipeline_impl_t;
void kinc_internal_set_constants(void);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,133 @@
#include <kinc/graphics4/rendertarget.h>
#include <kinc/log.h>
#include <kinc/backend/SystemMicrosoft.h>
#include "Direct3D9.h"
void kinc_g4_render_target_init_with_multisampling(kinc_g4_render_target_t *renderTarget, int width, int height, kinc_g4_render_target_format_t format,
int depthBufferBits, int stencilBufferBits, int samples_per_pixel) {
renderTarget->width = width;
renderTarget->height = height;
renderTarget->texWidth = width;
renderTarget->texHeight = height;
renderTarget->isCubeMap = false;
renderTarget->isDepthAttachment = false;
const bool antialiasing = samples_per_pixel > 1;
renderTarget->impl.antialiasing = antialiasing;
D3DFORMAT d3dformat;
switch (format) {
case KINC_G4_RENDER_TARGET_FORMAT_64BIT_FLOAT:
d3dformat = D3DFMT_A16B16G16R16F;
break;
case KINC_G4_RENDER_TARGET_FORMAT_32BIT_RED_FLOAT:
d3dformat = D3DFMT_R32F;
break;
case KINC_G4_RENDER_TARGET_FORMAT_32BIT:
default:
d3dformat = D3DFMT_A8R8G8B8;
}
#if defined(_DEBUG)
kinc_log(KINC_LOG_LEVEL_INFO, "depthBufferBits not implemented yet, using defaults (D3DFMT_D24S8)");
kinc_log(KINC_LOG_LEVEL_INFO, "stencilBufferBits not implemented yet, using defaults (D3DFMT_D24S8)");
#endif
renderTarget->impl.colorSurface = nullptr;
renderTarget->impl.depthSurface = nullptr;
renderTarget->impl.colorTexture = nullptr;
renderTarget->impl.depthTexture = nullptr;
if (antialiasing) {
kinc_microsoft_affirm(
device->CreateRenderTarget(width, height, d3dformat, D3DMULTISAMPLE_8_SAMPLES, 0, FALSE, &renderTarget->impl.colorSurface, nullptr));
kinc_microsoft_affirm(
device->CreateDepthStencilSurface(width, height, D3DFMT_D24S8, D3DMULTISAMPLE_8_SAMPLES, 0, TRUE, &renderTarget->impl.depthSurface, nullptr));
kinc_microsoft_affirm(
device->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET, d3dformat, D3DPOOL_DEFAULT, &renderTarget->impl.colorTexture, nullptr));
// Microsoft::affirm(device->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &depthTexture, nullptr));
renderTarget->impl.depthTexture = nullptr;
}
else {
if (format == KINC_G4_RENDER_TARGET_FORMAT_16BIT_DEPTH) {
kinc_microsoft_affirm(device->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET, (D3DFORMAT)MAKEFOURCC('N', 'U', 'L', 'L'), D3DPOOL_DEFAULT,
&renderTarget->impl.colorTexture, nullptr));
kinc_microsoft_affirm(device->CreateTexture(width, height, 1, D3DUSAGE_DEPTHSTENCIL, (D3DFORMAT)MAKEFOURCC('I', 'N', 'T', 'Z'), D3DPOOL_DEFAULT,
&renderTarget->impl.depthTexture, nullptr));
renderTarget->isDepthAttachment = true;
}
else {
kinc_microsoft_affirm(
device->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET, d3dformat, D3DPOOL_DEFAULT, &renderTarget->impl.colorTexture, nullptr));
kinc_microsoft_affirm(
device->CreateTexture(width, height, 1, D3DUSAGE_DEPTHSTENCIL, D3DFMT_D24S8, D3DPOOL_DEFAULT, &renderTarget->impl.depthTexture, nullptr));
}
kinc_microsoft_affirm(renderTarget->impl.colorTexture->GetSurfaceLevel(0, &renderTarget->impl.colorSurface));
kinc_microsoft_affirm(renderTarget->impl.depthTexture->GetSurfaceLevel(0, &renderTarget->impl.depthSurface));
}
}
void kinc_g4_render_target_init_cube_with_multisampling(kinc_g4_render_target_t *renderTarget, int cubeMapSize, kinc_g4_render_target_format_t format,
int depthBufferBits, int stencilBufferBits, int samples_per_pixel) {
renderTarget->isCubeMap = true;
renderTarget->isDepthAttachment = false;
}
void kinc_g4_render_target_destroy(kinc_g4_render_target_t *renderTarget) {
if (renderTarget->impl.colorSurface != nullptr) {
renderTarget->impl.colorSurface->Release();
}
if (renderTarget->impl.depthSurface != nullptr) {
renderTarget->impl.depthSurface->Release();
}
if (renderTarget->impl.colorTexture != nullptr) {
renderTarget->impl.colorTexture->Release();
}
if (renderTarget->impl.depthTexture != nullptr) {
renderTarget->impl.depthTexture->Release();
}
}
#ifdef KINC_KONG
void kinc_g4_render_target_use_color_as_texture(kinc_g4_render_target_t *renderTarget, uint32_t unit) {
if (renderTarget->impl.antialiasing) {
IDirect3DSurface9 *surface;
renderTarget->impl.colorTexture->GetSurfaceLevel(0, &surface);
kinc_microsoft_affirm(device->StretchRect(renderTarget->impl.colorSurface, nullptr, surface, nullptr, D3DTEXF_NONE));
surface->Release();
}
device->SetTexture(unit, renderTarget->isDepthAttachment ? renderTarget->impl.depthTexture : renderTarget->impl.colorTexture);
}
#else
void kinc_g4_render_target_use_color_as_texture(kinc_g4_render_target_t *renderTarget, kinc_g4_texture_unit_t unit) {
if (renderTarget->impl.antialiasing) {
IDirect3DSurface9 *surface;
renderTarget->impl.colorTexture->GetSurfaceLevel(0, &surface);
kinc_microsoft_affirm(device->StretchRect(renderTarget->impl.colorSurface, nullptr, surface, nullptr, D3DTEXF_NONE));
surface->Release();
}
device->SetTexture(unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT],
renderTarget->isDepthAttachment ? renderTarget->impl.depthTexture : renderTarget->impl.colorTexture);
}
#endif
void kinc_g4_render_target_set_depth_stencil_from(kinc_g4_render_target_t *renderTarget, kinc_g4_render_target_t *source) {
renderTarget->impl.depthTexture = source->impl.depthTexture;
renderTarget->impl.depthSurface = source->impl.depthSurface;
}
void kinc_g4_render_target_use_depth_as_texture(kinc_g4_render_target_t *renderTarget, kinc_g4_texture_unit_t unit) {
if (renderTarget->impl.antialiasing) {
IDirect3DSurface9 *surface;
renderTarget->impl.depthTexture->GetSurfaceLevel(0, &surface);
kinc_microsoft_affirm(device->StretchRect(renderTarget->impl.depthSurface, nullptr, surface, nullptr, D3DTEXF_NONE));
surface->Release();
}
device->SetTexture(unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], renderTarget->impl.depthTexture);
}
void kinc_g4_render_target_get_pixels(kinc_g4_render_target_t *renderTarget, uint8_t *data) {}
void kinc_g4_render_target_generate_mipmaps(kinc_g4_render_target_t *renderTarget, int levels) {}

View File

@ -0,0 +1,20 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
struct IDirect3DSurface9;
struct IDirect3DTexture9;
typedef struct {
struct IDirect3DSurface9 *colorSurface;
struct IDirect3DSurface9 *depthSurface;
struct IDirect3DTexture9 *colorTexture;
struct IDirect3DTexture9 *depthTexture;
bool antialiasing;
} kinc_g4_render_target_impl_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,54 @@
#include <kinc/graphics4/shader.h>
#include <kinc/math/core.h>
#include <kinc/backend/SystemMicrosoft.h>
#include "Direct3D9.h"
#include <cstdio>
void kinc_g4_shader_init(kinc_g4_shader_t *shader, const void *void_data, size_t length, kinc_g4_shader_type_t type) {
unsigned index = 0;
uint8_t *data = (uint8_t *)void_data;
int attributesCount = data[index++];
for (int i = 0; i < attributesCount; ++i) {
char name[256];
for (unsigned i2 = 0; i2 < 255; ++i2) {
name[i2] = data[index++];
if (name[i2] == 0)
break;
}
strcpy(shader->impl.attributes[i].name, name);
shader->impl.attributes[i].index = data[index++];
}
shader->impl.attributes[attributesCount].name[0] = 0;
uint8_t constantCount = data[index++];
for (unsigned i = 0; i < constantCount; ++i) {
char name[256];
for (unsigned i2 = 0; i2 < 255; ++i2) {
name[i2] = data[index++];
if (name[i2] == 0)
break;
}
strcpy(shader->impl.constants[i].name, name);
shader->impl.constants[i].regtype = data[index++];
shader->impl.constants[i].regindex = data[index++];
shader->impl.constants[i].regcount = data[index++];
}
shader->impl.constants[constantCount].name[0] = 0;
if (type == KINC_G4_SHADER_TYPE_VERTEX) {
kinc_microsoft_affirm(device->CreateVertexShader((DWORD *)&data[index], (IDirect3DVertexShader9 **)&shader));
}
else {
kinc_microsoft_affirm(device->CreatePixelShader((DWORD *)&data[index], (IDirect3DPixelShader9 **)&shader));
}
}
int kinc_g4_shader_init_from_source(kinc_g4_shader_t *shader, const char *source, kinc_g4_shader_type_t type) {
return 1;
}
void kinc_g4_shader_destroy(kinc_g4_shader_t *shader) {}

View File

@ -0,0 +1,41 @@
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
struct ShaderRegister {
char name[128];
uint8_t regtype;
uint8_t regindex;
uint8_t regcount;
};
struct ShaderAttribute {
char name[128];
int index;
};
typedef struct {
struct ShaderRegister reg;
int shaderType; // 0: Vertex, 1: Fragment
} kinc_g4_constant_location_impl_t;
typedef struct {
int unit;
} kinc_g4_texture_unit_impl_t;
#define KINC_INTERNAL_MAX_CONSTANTS 64
#define KINC_INTERNAL_MAX_ATTRIBUTES 64
typedef struct {
struct ShaderRegister constants[KINC_INTERNAL_MAX_CONSTANTS];
struct ShaderAttribute attributes[KINC_INTERNAL_MAX_ATTRIBUTES];
void *shader;
} kinc_g4_shader_impl_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,110 @@
#include <kinc/graphics4/texture.h>
#include <kinc/io/filereader.h>
#include <kinc/backend/SystemMicrosoft.h>
#include "Direct3D9.h"
namespace {
kinc_g4_texture_t *setTextures[16] = {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr};
D3DFORMAT convert(kinc_image_format_t format) {
switch (format) {
case KINC_IMAGE_FORMAT_RGBA32:
default:
return D3DFMT_A8R8G8B8;
case KINC_IMAGE_FORMAT_GREY8:
return D3DFMT_L8;
}
}
}
void kinc_g4_texture_init_from_image(kinc_g4_texture_t *texture, kinc_image_t *image) {
texture->impl.stage = 0;
texture->impl.mipmap = true;
DWORD usage = 0;
texture->tex_width = image->width;
texture->tex_height = image->height;
texture->tex_depth = 1;
usage = D3DUSAGE_DYNAMIC;
kinc_microsoft_affirm_message(
device->CreateTexture(image->width, image->height, 1, usage, convert(image->format), D3DPOOL_DEFAULT, &texture->impl.texture, 0),
"Texture creation failed.");
D3DLOCKED_RECT rect;
kinc_microsoft_affirm(texture->impl.texture->LockRect(0, &rect, 0, 0));
texture->impl.pitch = rect.Pitch;
uint8_t *from = (uint8_t *)image->data;
uint8_t *to = (uint8_t *)rect.pBits;
// memcpy(to, from, width * height * sizeOf(format));
for (int y = 0; y < image->height; ++y) {
for (int x = 0; x < image->width; ++x) {
to[rect.Pitch * y + x * 4 + 0 /* blue*/] = (from[y * image->width * 4 + x * 4 + 2]); /// 255.0f;
to[rect.Pitch * y + x * 4 + 1 /*green*/] = (from[y * image->width * 4 + x * 4 + 1]); /// 255.0f;
to[rect.Pitch * y + x * 4 + 2 /* red*/] = (from[y * image->width * 4 + x * 4 + 0]); /// 255.0f;
to[rect.Pitch * y + x * 4 + 3 /*alpha*/] = (from[y * image->width * 4 + x * 4 + 3]); /// 255.0f;
}
}
kinc_microsoft_affirm(texture->impl.texture->UnlockRect(0));
}
void kinc_g4_texture_init3d(kinc_g4_texture_t *texture, int width, int height, int depth, kinc_image_format_t format) {}
void kinc_g4_texture_init(kinc_g4_texture_t *texture, int width, int height, kinc_image_format_t format) {
texture->impl.stage = 0;
texture->impl.mipmap = true;
DWORD usage = 0;
texture->tex_width = width;
texture->tex_height = height;
texture->tex_depth = 1;
usage = D3DUSAGE_DYNAMIC;
kinc_microsoft_affirm_message(device->CreateTexture(width, height, 1, usage, convert(format), D3DPOOL_DEFAULT, &texture->impl.texture, 0),
"Texture creation failed.");
}
void kinc_g4_texture_destroy(kinc_g4_texture_t *texture) {
kinc_internal_texture_unset(texture);
texture->impl.texture->Release();
}
#ifdef KINC_KONG
void kinc_internal_texture_set(kinc_g4_texture_t *texture, uint32_t unit) {
kinc_microsoft_affirm(device->SetTexture(unit, texture->impl.texture));
texture->impl.stage = unit;
setTextures[texture->impl.stage] = texture;
}
#else
void kinc_internal_texture_set(kinc_g4_texture_t *texture, kinc_g4_texture_unit_t unit) {
kinc_microsoft_affirm(device->SetTexture(unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], texture->impl.texture));
texture->impl.stage = unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT];
setTextures[texture->impl.stage] = texture;
}
#endif
void kinc_internal_texture_unset(struct kinc_g4_texture *texture) {
if (setTextures[texture->impl.stage] == texture) {
device->SetTexture(texture->impl.stage, nullptr);
setTextures[texture->impl.stage] = nullptr;
}
}
unsigned char *kinc_g4_texture_lock(kinc_g4_texture_t *texture) {
D3DLOCKED_RECT rect;
kinc_microsoft_affirm(texture->impl.texture->LockRect(0, &rect, 0, 0));
texture->impl.pitch = rect.Pitch;
return (uint8_t *)rect.pBits;
}
void kinc_g4_texture_unlock(kinc_g4_texture_t *texture) {
kinc_microsoft_affirm(texture->impl.texture->UnlockRect(0));
}
void kinc_g4_texture_clear(kinc_g4_texture_t *texture, int x, int y, int z, int width, int height, int depth, unsigned color) {}
int kinc_g4_texture_stride(kinc_g4_texture_t *texture) {
return texture->impl.pitch;
}
void kinc_g4_texture_generate_mipmaps(kinc_g4_texture_t *texture, int levels) {}
void kinc_g4_texture_set_mipmap(kinc_g4_texture_t *texture, kinc_image_t *mipmap, int level) {}

View File

@ -0,0 +1,26 @@
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
struct IDirect3DTexture9;
typedef struct {
struct IDirect3DTexture9 *texture;
int stage;
bool mipmap;
uint8_t pixfmt;
int pitch;
} kinc_g4_texture_impl_t;
struct kinc_g4_texture;
void kinc_internal_texture_unmipmap(struct kinc_g4_texture *texture);
void kinc_internal_texture_unset(struct kinc_g4_texture *texture);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,5 @@
#include <kinc/graphics4/texturearray.h>
void kinc_g4_texture_array_init(kinc_g4_texture_array_t *array, kinc_image_t *textures, int count) {}
void kinc_g4_texture_array_destroy(kinc_g4_texture_array_t *array) {}

View File

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

View File

@ -0,0 +1,75 @@
#include <kinc/graphics4/graphics.h>
#include <kinc/graphics4/vertexbuffer.h>
#include <kinc/backend/SystemMicrosoft.h>
#include "Direct3D9.h"
struct kinc_g4_vertex_buffer *kinc_internal_current_vertex_buffer = NULL;
void kinc_g4_vertex_buffer_init(kinc_g4_vertex_buffer_t *buffer, int count, kinc_g4_vertex_structure_t *structure, kinc_g4_usage_t usage,
int instance_data_step_rate) {
buffer->impl.myCount = count;
buffer->impl.instanceDataStepRate = instance_data_step_rate;
DWORD usageFlags = D3DUSAGE_WRITEONLY;
if (usage == KINC_G4_USAGE_DYNAMIC) {
usageFlags = D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY;
}
buffer->impl.myStride = 0;
for (int i = 0; i < structure->size; ++i) {
buffer->impl.myStride += kinc_g4_vertex_data_size(structure->elements[i].data);
}
kinc_microsoft_affirm(device->CreateVertexBuffer(kinc_g4_vertex_buffer_stride(buffer) * count, usageFlags, 0, D3DPOOL_DEFAULT, &buffer->impl.vb, 0));
}
void kinc_g4_vertex_buffer_destroy(kinc_g4_vertex_buffer_t *buffer) {
buffer->impl.vb->Release();
}
float *kinc_g4_vertex_buffer_lock_all(kinc_g4_vertex_buffer_t *buffer) {
return kinc_g4_vertex_buffer_lock(buffer, 0, kinc_g4_vertex_buffer_count(buffer));
}
float *kinc_g4_vertex_buffer_lock(kinc_g4_vertex_buffer_t *buffer, int start, int count) {
float *vertices;
kinc_internal_vertex_buffer_unset(buffer);
kinc_microsoft_affirm(buffer->impl.vb->Lock(start, count * kinc_g4_vertex_buffer_stride(buffer), (void **)&vertices, D3DLOCK_DISCARD));
return vertices;
}
void kinc_g4_vertex_buffer_unlock_all(kinc_g4_vertex_buffer_t *buffer) {
kinc_microsoft_affirm(buffer->impl.vb->Unlock());
}
void kinc_g4_vertex_buffer_unlock(kinc_g4_vertex_buffer_t *buffer, int count) {
kinc_microsoft_affirm(buffer->impl.vb->Unlock());
}
int kinc_internal_g4_vertex_buffer_set(kinc_g4_vertex_buffer_t *buffer, int offset) {
buffer->impl._offset = offset;
if (buffer->impl.instanceDataStepRate == 0) {
kinc_internal_current_vertex_buffer = buffer;
}
else {
kinc_microsoft_affirm(device->SetStreamSourceFreq(offset, (D3DSTREAMSOURCE_INSTANCEDATA | buffer->impl.instanceDataStepRate)));
}
kinc_microsoft_affirm(device->SetStreamSource(offset, buffer->impl.vb, 0, kinc_g4_vertex_buffer_stride(buffer)));
return 0;
}
void kinc_internal_vertex_buffer_unset(struct kinc_g4_vertex_buffer *buffer) {
if (kinc_internal_current_vertex_buffer == buffer) {
kinc_microsoft_affirm(device->SetStreamSource(0, NULL, 0, 0));
kinc_internal_current_vertex_buffer = NULL;
}
}
int kinc_g4_vertex_buffer_count(kinc_g4_vertex_buffer_t *buffer) {
return buffer->impl.myCount;
}
int kinc_g4_vertex_buffer_stride(kinc_g4_vertex_buffer_t *buffer) {
return buffer->impl.myStride;
}

View File

@ -0,0 +1,25 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
struct IDirect3DVertexBuffer9;
typedef struct {
struct IDirect3DVertexBuffer9 *vb;
int myCount;
int myStride;
int instanceDataStepRate;
int _offset;
} kinc_g4_vertex_buffer_impl_t;
struct kinc_g4_vertex_buffer;
void kinc_internal_vertex_buffer_unset(struct kinc_g4_vertex_buffer *buffer);
extern struct kinc_g4_vertex_buffer *kinc_internal_current_vertex_buffer;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,841 @@
#include "G4.h"
#include "kinc/graphics4/graphics.h"
#include "kinc/window.h"
#include <kinc/backend/graphics4/indexbuffer.h>
#include <kinc/backend/graphics4/pipeline.h>
#include <kinc/backend/graphics4/vertexbuffer.h>
#include <kinc/color.h>
#include <kinc/graphics4/compute.h>
#include <kinc/graphics4/constantbuffer.h>
#include <kinc/graphics4/indexbuffer.h>
#include <kinc/graphics4/pipeline.h>
#include <kinc/graphics4/rendertarget.h>
#include <kinc/graphics4/shader.h>
#include <kinc/graphics4/texture.h>
#include <kinc/graphics4/texturearray.h>
#include <kinc/graphics4/vertexbuffer.h>
#include <kinc/graphics5/commandlist.h>
#include <kinc/graphics5/constantbuffer.h>
#include <kinc/graphics5/graphics.h>
#include <kinc/graphics5/sampler.h>
#include <kinc/io/filereader.h>
#include <kinc/math/core.h>
#include <kinc/math/matrix.h>
#include <kinc/system.h>
#include <assert.h>
#include <string.h>
kinc_g5_command_list_t commandList;
uint64_t frameNumber = 0;
bool waitAfterNextDraw = false;
static kinc_g5_constant_buffer_t vertexConstantBuffer;
static kinc_g5_constant_buffer_t fragmentConstantBuffer;
#define constantBufferSize 4096
#define constantBufferMultiply 100
static int constantBufferIndex = 0;
void kinc_g4_internal_init(void) {
kinc_g5_internal_init();
}
void kinc_g4_internal_destroy(void) {
kinc_g5_internal_destroy();
}
void kinc_g4_internal_destroy_window(int window) {
kinc_g5_internal_destroy_window(window);
}
#define bufferCount 2
#define renderTargetCount 8
static struct {
int currentBuffer;
kinc_g5_render_target_t framebuffers[bufferCount];
kinc_g4_render_target_t *current_render_targets[renderTargetCount];
int current_render_target_count;
bool resized;
} windows[16] = {0};
static int current_window;
#define MAX_VERTEX_BUFFERS 16
#define MAX_TEXTURES 16
typedef struct render_state {
kinc_g5_pipeline_t *pipeline;
kinc_g5_index_buffer_t *index_buffer;
kinc_g5_vertex_buffer_t *vertex_buffers[MAX_VERTEX_BUFFERS];
int vertex_buffer_offsets[MAX_VERTEX_BUFFERS];
int vertex_buffer_count;
bool blend_constant_set;
float blend_constant_r;
float blend_constant_g;
float blend_constant_b;
float blend_constant_a;
bool viewport_set;
int viewport_x;
int viewport_y;
int viewport_width;
int viewport_height;
bool scissor_set;
int scissor_x;
int scissor_y;
int scissor_width;
int scissor_height;
kinc_g5_texture_t *textures[MAX_TEXTURES];
kinc_g5_texture_unit_t texture_units[MAX_TEXTURES];
int texture_count;
kinc_g5_render_target_t *render_targets[MAX_TEXTURES];
kinc_g5_texture_unit_t render_target_units[MAX_TEXTURES];
int render_target_count;
kinc_g5_render_target_t *depth_render_targets[MAX_TEXTURES];
kinc_g5_texture_unit_t depth_render_target_units[MAX_TEXTURES];
int depth_render_target_count;
uint8_t vertex_constant_data[constantBufferSize];
uint8_t fragment_constant_data[constantBufferSize];
} render_state;
static render_state current_state;
void kinc_g4_on_g5_internal_resize(int window, int width, int height) {
windows[window].resized = true;
}
void kinc_g4_on_g5_internal_restore_render_target(void) {
windows[current_window].current_render_targets[0] = NULL;
kinc_g5_render_target_t *render_target = &windows[current_window].framebuffers[windows[current_window].currentBuffer];
kinc_g5_command_list_set_render_targets(&commandList, &render_target, 1);
windows[current_window].current_render_target_count = 1;
}
void kinc_g4_internal_init_window(int window, int depthBufferBits, int stencilBufferBits, bool vsync) {
kinc_g5_internal_init_window(window, depthBufferBits, stencilBufferBits, vsync);
kinc_g5_command_list_init(&commandList);
windows[window].currentBuffer = -1;
for (int i = 0; i < bufferCount; ++i) {
kinc_g5_render_target_init_framebuffer(&windows[window].framebuffers[i], kinc_window_width(window), kinc_window_height(window),
KINC_G5_RENDER_TARGET_FORMAT_32BIT, depthBufferBits, 0);
}
kinc_g5_constant_buffer_init(&vertexConstantBuffer, constantBufferSize * constantBufferMultiply);
kinc_g5_constant_buffer_init(&fragmentConstantBuffer, constantBufferSize * constantBufferMultiply);
// to support doing work after kinc_g4_end and before kinc_g4_begin
kinc_g5_command_list_begin(&commandList);
}
void kinc_g4_on_g5_internal_set_samplers(int count, kinc_g5_texture_unit_t *texture_units) {
for (int i = 0; i < count; ++i) {
for (int j = 0; j < KINC_G5_SHADER_TYPE_COUNT; ++j) {
if (texture_units[i].stages[j] >= 0) {
kinc_g5_sampler_t *sampler = get_current_sampler(j, texture_units[i].stages[j]);
kinc_g5_texture_unit_t unit;
for (int k = 0; k < KINC_G5_SHADER_TYPE_COUNT; ++k) {
unit.stages[k] = -1;
}
unit.stages[j] = texture_units[i].stages[j];
kinc_g5_command_list_set_sampler(&commandList, unit, sampler);
}
}
}
}
static void startDraw(void) {
if ((constantBufferIndex + 1) >= constantBufferMultiply || waitAfterNextDraw) {
memcpy(current_state.vertex_constant_data, vertexConstantBuffer.data, constantBufferSize);
memcpy(current_state.fragment_constant_data, fragmentConstantBuffer.data, constantBufferSize);
}
kinc_g5_constant_buffer_unlock(&vertexConstantBuffer);
kinc_g5_constant_buffer_unlock(&fragmentConstantBuffer);
kinc_g4_on_g5_internal_set_samplers(current_state.texture_count, current_state.texture_units);
kinc_g4_on_g5_internal_set_samplers(current_state.render_target_count, current_state.render_target_units);
kinc_g4_on_g5_internal_set_samplers(current_state.depth_render_target_count, current_state.depth_render_target_units);
kinc_g5_command_list_set_vertex_constant_buffer(&commandList, &vertexConstantBuffer, constantBufferIndex * constantBufferSize, constantBufferSize);
kinc_g5_command_list_set_fragment_constant_buffer(&commandList, &fragmentConstantBuffer, constantBufferIndex * constantBufferSize, constantBufferSize);
}
static void endDraw(void) {
++constantBufferIndex;
if (constantBufferIndex >= constantBufferMultiply || waitAfterNextDraw) {
kinc_g5_command_list_end(&commandList);
kinc_g5_command_list_execute(&commandList);
kinc_g5_command_list_wait_for_execution_to_finish(&commandList);
kinc_g5_command_list_begin(&commandList);
if (windows[current_window].current_render_targets[0] == NULL) {
kinc_g4_on_g5_internal_restore_render_target();
}
else {
const int count = windows[current_window].current_render_target_count;
kinc_g5_render_target_t *render_targets[16];
for (int i = 0; i < count; ++i) {
render_targets[i] = &windows[current_window].current_render_targets[i]->impl._renderTarget;
}
kinc_g5_command_list_set_render_targets(&commandList, render_targets, count);
}
if (current_state.pipeline != NULL) {
kinc_g5_command_list_set_pipeline(&commandList, current_state.pipeline);
}
if (current_state.index_buffer != NULL) {
kinc_g5_command_list_set_index_buffer(&commandList, current_state.index_buffer);
}
if (current_state.vertex_buffer_count > 0) {
kinc_g5_command_list_set_vertex_buffers(&commandList, current_state.vertex_buffers, current_state.vertex_buffer_offsets,
current_state.vertex_buffer_count);
}
if (current_state.blend_constant_set) {
kinc_g5_command_list_set_blend_constant(&commandList, current_state.blend_constant_r, current_state.blend_constant_g,
current_state.blend_constant_b, current_state.blend_constant_a);
}
if (current_state.viewport_set) {
kinc_g5_command_list_viewport(&commandList, current_state.viewport_x, current_state.viewport_y, current_state.viewport_width,
current_state.viewport_height);
}
if (current_state.scissor_set) {
kinc_g5_command_list_scissor(&commandList, current_state.scissor_x, current_state.scissor_y, current_state.scissor_width,
current_state.scissor_height);
}
for (int i = 0; i < current_state.texture_count; ++i) {
kinc_g5_command_list_set_texture(&commandList, current_state.texture_units[i], current_state.textures[i]);
}
for (int i = 0; i < current_state.render_target_count; ++i) {
kinc_g5_command_list_set_texture_from_render_target(&commandList, current_state.render_target_units[i], current_state.render_targets[i]);
}
for (int i = 0; i < current_state.depth_render_target_count; ++i) {
kinc_g5_command_list_set_texture_from_render_target_depth(&commandList, current_state.depth_render_target_units[i],
current_state.depth_render_targets[i]);
}
constantBufferIndex = 0;
waitAfterNextDraw = false;
kinc_g5_constant_buffer_lock(&vertexConstantBuffer, 0, constantBufferSize);
kinc_g5_constant_buffer_lock(&fragmentConstantBuffer, 0, constantBufferSize);
memcpy(vertexConstantBuffer.data, current_state.vertex_constant_data, constantBufferSize);
memcpy(fragmentConstantBuffer.data, current_state.fragment_constant_data, constantBufferSize);
}
else {
kinc_g5_constant_buffer_lock(&vertexConstantBuffer, constantBufferIndex * constantBufferSize, constantBufferSize);
kinc_g5_constant_buffer_lock(&fragmentConstantBuffer, constantBufferIndex * constantBufferSize, constantBufferSize);
}
}
void kinc_g4_draw_indexed_vertices(void) {
startDraw();
kinc_g5_command_list_draw_indexed_vertices(&commandList);
endDraw();
}
void kinc_g4_draw_indexed_vertices_from_to(int start, int count) {
startDraw();
kinc_g5_command_list_draw_indexed_vertices_from_to(&commandList, start, count);
endDraw();
}
void kinc_g4_draw_indexed_vertices_from_to_from(int start, int count, int vertex_offset) {
startDraw();
kinc_g5_command_list_draw_indexed_vertices_from_to_from(&commandList, start, count, vertex_offset);
endDraw();
}
void kinc_g4_draw_indexed_vertices_instanced(int instanceCount) {
startDraw();
kinc_g5_command_list_draw_indexed_vertices_instanced(&commandList, instanceCount);
endDraw();
}
void kinc_g4_draw_indexed_vertices_instanced_from_to(int instanceCount, int start, int count) {
startDraw();
kinc_g5_command_list_draw_indexed_vertices_instanced_from_to(&commandList, instanceCount, start, count);
endDraw();
}
void kinc_g4_clear(unsigned flags, unsigned color, float depth, int stencil) {
if (windows[current_window].current_render_target_count > 0) {
if (windows[current_window].current_render_targets[0] == NULL) {
kinc_g5_command_list_clear(&commandList, &windows[current_window].framebuffers[windows[current_window].currentBuffer], flags, color, depth,
stencil);
}
else {
if (windows[current_window].current_render_targets[0]->impl.state != KINC_INTERNAL_RENDER_TARGET_STATE_RENDER_TARGET) {
kinc_g5_command_list_texture_to_render_target_barrier(&commandList, &windows[current_window].current_render_targets[0]->impl._renderTarget);
windows[current_window].current_render_targets[0]->impl.state = KINC_INTERNAL_RENDER_TARGET_STATE_RENDER_TARGET;
}
kinc_g5_command_list_clear(&commandList, &windows[current_window].current_render_targets[0]->impl._renderTarget, flags, color, depth, stencil);
}
}
}
bool first_run = true;
void kinc_g4_begin(int window) {
// to support doing work after kinc_g4_end and before kinc_g4_begin
kinc_g5_command_list_end(&commandList);
kinc_g5_command_list_execute(&commandList);
current_window = window;
windows[current_window].currentBuffer = (windows[current_window].currentBuffer + 1) % bufferCount;
bool resized = windows[window].resized;
if (resized) {
for (int i = 0; i < bufferCount; ++i) {
kinc_g5_render_target_destroy(&windows[current_window].framebuffers[i]);
}
windows[current_window].currentBuffer = 0;
}
kinc_g5_begin(&windows[current_window].framebuffers[windows[current_window].currentBuffer], window);
if (resized) {
for (int i = 0; i < bufferCount; ++i) {
kinc_g5_render_target_init_framebuffer(&windows[current_window].framebuffers[i], kinc_window_width(window), kinc_window_height(window),
KINC_G5_RENDER_TARGET_FORMAT_32BIT, 16, 0);
}
windows[window].resized = false;
}
windows[current_window].current_render_targets[0] = NULL;
windows[current_window].current_render_target_count = 1;
current_state.pipeline = NULL;
current_state.index_buffer = NULL;
for (int i = 0; i < MAX_VERTEX_BUFFERS; ++i) {
current_state.vertex_buffers[i] = NULL;
current_state.vertex_buffer_offsets[i] = 0;
}
current_state.vertex_buffer_count = 0;
current_state.blend_constant_set = false;
current_state.viewport_set = false;
current_state.scissor_set = false;
current_state.texture_count = 0;
current_state.render_target_count = 0;
current_state.depth_render_target_count = 0;
samplers_reset();
// commandList = new Graphics5::CommandList;
kinc_g5_command_list_begin(&commandList);
// Currently we do not necessarily wait at the end of a frame so for now it's endDraw
// constantBufferIndex = 0;
// kinc_g5_constant_buffer_lock(&vertexConstantBuffer, 0, constantBufferSize);
// kinc_g5_constant_buffer_lock(&fragmentConstantBuffer, 0, constantBufferSize);
endDraw();
kinc_g5_command_list_framebuffer_to_render_target_barrier(&commandList, &windows[current_window].framebuffers[windows[current_window].currentBuffer]);
kinc_g4_restore_render_target();
++frameNumber;
}
void kinc_g4_viewport(int x, int y, int width, int height) {
current_state.viewport_x = x;
current_state.viewport_y = y;
current_state.viewport_width = width;
current_state.viewport_height = height;
current_state.viewport_set = true;
kinc_g5_command_list_viewport(&commandList, x, y, width, height);
}
void kinc_g4_scissor(int x, int y, int width, int height) {
current_state.scissor_x = x;
current_state.scissor_y = y;
current_state.scissor_width = width;
current_state.scissor_height = height;
current_state.scissor_set = true;
kinc_g5_command_list_scissor(&commandList, x, y, width, height);
}
void kinc_g4_disable_scissor(void) {
current_state.scissor_set = false;
kinc_g5_command_list_disable_scissor(&commandList);
}
void kinc_g4_end(int window) {
kinc_g5_constant_buffer_unlock(&vertexConstantBuffer);
kinc_g5_constant_buffer_unlock(&fragmentConstantBuffer);
kinc_g5_command_list_render_target_to_framebuffer_barrier(&commandList, &windows[current_window].framebuffers[windows[current_window].currentBuffer]);
kinc_g5_command_list_end(&commandList);
kinc_g5_command_list_execute(&commandList);
// delete commandList;
// commandList = nullptr;
kinc_g5_end(window);
// to support doing work after kinc_g4_end and before kinc_g4_begin
kinc_g5_command_list_begin(&commandList);
}
/*void Graphics4::_changeFramebuffer(int window, Kore::FramebufferOptions* frame) {
}*/
bool kinc_g4_swap_buffers(void) {
return kinc_g5_swap_buffers();
}
void kinc_g4_flush(void) {
kinc_g5_flush();
}
void kinc_g4_set_stencil_reference_value(int value) {}
void kinc_g4_set_int(kinc_g4_constant_location_t location, int value) {
if (location.impl._location.impl.vertexOffset >= 0)
kinc_g5_constant_buffer_set_int(&vertexConstantBuffer, location.impl._location.impl.vertexOffset, value);
if (location.impl._location.impl.fragmentOffset >= 0)
kinc_g5_constant_buffer_set_int(&fragmentConstantBuffer, location.impl._location.impl.fragmentOffset, value);
}
void kinc_g4_set_int2(kinc_g4_constant_location_t location, int value1, int value2) {}
void kinc_g4_set_int3(kinc_g4_constant_location_t location, int value1, int value2, int value3) {}
void kinc_g4_set_int4(kinc_g4_constant_location_t location, int value1, int value2, int value3, int value4) {}
void kinc_g4_set_ints(kinc_g4_constant_location_t location, int *values, int count) {}
void kinc_g4_set_float(kinc_g4_constant_location_t location, float value) {
if (location.impl._location.impl.vertexOffset >= 0)
kinc_g5_constant_buffer_set_float(&vertexConstantBuffer, location.impl._location.impl.vertexOffset, value);
if (location.impl._location.impl.fragmentOffset >= 0)
kinc_g5_constant_buffer_set_float(&fragmentConstantBuffer, location.impl._location.impl.fragmentOffset, value);
}
void kinc_g4_set_float2(kinc_g4_constant_location_t location, float value1, float value2) {
if (location.impl._location.impl.vertexOffset >= 0)
kinc_g5_constant_buffer_set_float2(&vertexConstantBuffer, location.impl._location.impl.vertexOffset, value1, value2);
if (location.impl._location.impl.fragmentOffset >= 0)
kinc_g5_constant_buffer_set_float2(&fragmentConstantBuffer, location.impl._location.impl.fragmentOffset, value1, value2);
}
void kinc_g4_set_float3(kinc_g4_constant_location_t location, float value1, float value2, float value3) {
if (location.impl._location.impl.vertexOffset >= 0)
kinc_g5_constant_buffer_set_float3(&vertexConstantBuffer, location.impl._location.impl.vertexOffset, value1, value2, value3);
if (location.impl._location.impl.fragmentOffset >= 0)
kinc_g5_constant_buffer_set_float3(&fragmentConstantBuffer, location.impl._location.impl.fragmentOffset, value1, value2, value3);
}
void kinc_g4_set_float4(kinc_g4_constant_location_t location, float value1, float value2, float value3, float value4) {
if (location.impl._location.impl.vertexOffset >= 0)
kinc_g5_constant_buffer_set_float4(&vertexConstantBuffer, location.impl._location.impl.vertexOffset, value1, value2, value3, value4);
if (location.impl._location.impl.fragmentOffset >= 0)
kinc_g5_constant_buffer_set_float4(&fragmentConstantBuffer, location.impl._location.impl.fragmentOffset, value1, value2, value3, value4);
}
void kinc_g4_set_floats(kinc_g4_constant_location_t location, float *values, int count) {
if (location.impl._location.impl.vertexOffset >= 0)
kinc_g5_constant_buffer_set_floats(&vertexConstantBuffer, location.impl._location.impl.vertexOffset, values, count);
if (location.impl._location.impl.fragmentOffset >= 0)
kinc_g5_constant_buffer_set_floats(&fragmentConstantBuffer, location.impl._location.impl.fragmentOffset, values, count);
}
void kinc_g4_set_bool(kinc_g4_constant_location_t location, bool value) {
if (location.impl._location.impl.vertexOffset >= 0)
kinc_g5_constant_buffer_set_bool(&vertexConstantBuffer, location.impl._location.impl.vertexOffset, value);
if (location.impl._location.impl.fragmentOffset >= 0)
kinc_g5_constant_buffer_set_bool(&fragmentConstantBuffer, location.impl._location.impl.fragmentOffset, value);
}
void kinc_g4_set_matrix4(kinc_g4_constant_location_t location, kinc_matrix4x4_t *value) {
if (location.impl._location.impl.vertexOffset >= 0)
kinc_g5_constant_buffer_set_matrix4(&vertexConstantBuffer, location.impl._location.impl.vertexOffset, value);
if (location.impl._location.impl.fragmentOffset >= 0)
kinc_g5_constant_buffer_set_matrix4(&fragmentConstantBuffer, location.impl._location.impl.fragmentOffset, value);
}
void kinc_g4_set_matrix3(kinc_g4_constant_location_t location, kinc_matrix3x3_t *value) {
if (location.impl._location.impl.vertexOffset >= 0)
kinc_g5_constant_buffer_set_matrix3(&vertexConstantBuffer, location.impl._location.impl.vertexOffset, value);
if (location.impl._location.impl.fragmentOffset >= 0)
kinc_g5_constant_buffer_set_matrix3(&fragmentConstantBuffer, location.impl._location.impl.fragmentOffset, value);
}
void kinc_g4_set_texture_addressing(kinc_g4_texture_unit_t unit, kinc_g4_texture_direction_t dir, kinc_g4_texture_addressing_t addressing) {
for (int i = 0; i < KINC_G5_SHADER_TYPE_COUNT; ++i) {
if (unit.stages[i] >= 0) {
if (dir == KINC_G4_TEXTURE_DIRECTION_U) {
sampler_options[i][unit.stages[i]].u_addressing = (kinc_g5_texture_addressing_t)addressing;
}
if (dir == KINC_G4_TEXTURE_DIRECTION_V) {
sampler_options[i][unit.stages[i]].v_addressing = (kinc_g5_texture_addressing_t)addressing;
}
if (dir == KINC_G4_TEXTURE_DIRECTION_W) {
sampler_options[i][unit.stages[i]].w_addressing = (kinc_g5_texture_addressing_t)addressing;
}
}
}
}
void kinc_g4_set_texture3d_addressing(kinc_g4_texture_unit_t unit, kinc_g4_texture_direction_t dir, kinc_g4_texture_addressing_t addressing) {
kinc_g4_set_texture_addressing(unit, dir, addressing);
}
void kinc_g4_set_texture_magnification_filter(kinc_g4_texture_unit_t texunit, kinc_g4_texture_filter_t filter) {
for (int i = 0; i < KINC_G5_SHADER_TYPE_COUNT; ++i) {
if (texunit.stages[i] >= 0) {
sampler_options[i][texunit.stages[i]].magnification_filter = (kinc_g5_texture_filter_t)filter;
}
}
}
void kinc_g4_set_texture3d_magnification_filter(kinc_g4_texture_unit_t texunit, kinc_g4_texture_filter_t filter) {
kinc_g4_set_texture_magnification_filter(texunit, filter);
}
void kinc_g4_set_texture_minification_filter(kinc_g4_texture_unit_t texunit, kinc_g4_texture_filter_t filter) {
for (int i = 0; i < KINC_G5_SHADER_TYPE_COUNT; ++i) {
if (texunit.stages[i] >= 0) {
sampler_options[i][texunit.stages[i]].minification_filter = (kinc_g5_texture_filter_t)filter;
}
}
}
void kinc_g4_set_texture3d_minification_filter(kinc_g4_texture_unit_t texunit, kinc_g4_texture_filter_t filter) {
kinc_g4_set_texture_minification_filter(texunit, filter);
}
void kinc_g4_set_texture_mipmap_filter(kinc_g4_texture_unit_t texunit, kinc_g4_mipmap_filter_t filter) {
for (int i = 0; i < KINC_G5_SHADER_TYPE_COUNT; ++i) {
if (texunit.stages[i] >= 0) {
sampler_options[i][texunit.stages[i]].mipmap_filter = (kinc_g5_mipmap_filter_t)filter;
}
}
}
void kinc_g4_set_texture3d_mipmap_filter(kinc_g4_texture_unit_t texunit, kinc_g4_mipmap_filter_t filter) {
kinc_g4_set_texture_mipmap_filter(texunit, filter);
}
void kinc_g4_set_texture_compare_mode(kinc_g4_texture_unit_t unit, bool enabled) {
for (int i = 0; i < KINC_G5_SHADER_TYPE_COUNT; ++i) {
if (unit.stages[i] >= 0) {
sampler_options[i][unit.stages[i]].is_comparison = enabled;
}
}
}
void kinc_g4_set_texture_compare_func(kinc_g4_texture_unit_t unit, kinc_g4_compare_mode_t mode) {
for (int i = 0; i < KINC_G5_SHADER_TYPE_COUNT; ++i) {
if (unit.stages[i] >= 0) {
sampler_options[i][unit.stages[i]].compare_mode = (kinc_g5_compare_mode_t)mode;
}
}
}
void kinc_g4_set_cubemap_compare_mode(kinc_g4_texture_unit_t unit, bool enabled) {}
void kinc_g4_set_cubemap_compare_func(kinc_g4_texture_unit_t unit, kinc_g4_compare_mode_t mode) {}
void kinc_g4_set_texture_max_anisotropy(kinc_g4_texture_unit_t unit, uint16_t max_anisotropy) {
for (int i = 0; i < KINC_G5_SHADER_TYPE_COUNT; ++i) {
if (unit.stages[i] >= 0) {
sampler_options[i][unit.stages[i]].max_anisotropy = max_anisotropy;
}
}
}
void kinc_g4_set_cubemap_max_anisotropy(kinc_g4_texture_unit_t unit, uint16_t max_anisotropy) {}
void kinc_g4_set_texture_lod(kinc_g4_texture_unit_t unit, float lod_min_clamp, float lod_max_clamp) {
for (int i = 0; i < KINC_G5_SHADER_TYPE_COUNT; ++i) {
if (unit.stages[i] >= 0) {
sampler_options[i][unit.stages[i]].lod_min_clamp = lod_min_clamp;
sampler_options[i][unit.stages[i]].lod_max_clamp = lod_max_clamp;
}
}
}
void kinc_g4_set_cubemap_lod(kinc_g4_texture_unit_t unit, float lod_min_clamp, float lod_max_clamp) {}
void kinc_g4_restore_render_target(void) {
kinc_g4_on_g5_internal_restore_render_target();
current_state.viewport_set = false;
current_state.scissor_set = false;
}
void kinc_g4_set_render_targets(kinc_g4_render_target_t **targets, int count) {
for (int i = 0; i < count; ++i) {
windows[current_window].current_render_targets[i] = targets[i];
if (windows[current_window].current_render_targets[i]->impl.state != KINC_INTERNAL_RENDER_TARGET_STATE_RENDER_TARGET) {
kinc_g5_command_list_texture_to_render_target_barrier(&commandList, &windows[current_window].current_render_targets[i]->impl._renderTarget);
windows[current_window].current_render_targets[i]->impl.state = KINC_INTERNAL_RENDER_TARGET_STATE_RENDER_TARGET;
}
}
windows[current_window].current_render_target_count = count;
kinc_g5_render_target_t *render_targets[16];
assert(count <= 16);
for (int i = 0; i < count; ++i) {
render_targets[i] = &targets[i]->impl._renderTarget;
}
kinc_g5_command_list_set_render_targets(&commandList, render_targets, count);
current_state.viewport_set = false;
current_state.scissor_set = false;
}
void kinc_g4_set_render_target_face(kinc_g4_render_target_t *texture, int face) {
kinc_g5_command_list_set_render_target_face(&commandList, &texture->impl._renderTarget, face);
current_state.viewport_set = false;
current_state.scissor_set = false;
}
void kinc_g4_set_vertex_buffers(kinc_g4_vertex_buffer_t **buffers, int count) {
assert(count <= MAX_VERTEX_BUFFERS);
for (int i = 0; i < count; ++i) {
current_state.vertex_buffers[i] = &buffers[i]->impl._buffer;
int index = buffers[i]->impl._currentIndex;
current_state.vertex_buffer_offsets[i] = index * kinc_g4_vertex_buffer_count(buffers[i]);
}
current_state.vertex_buffer_count = count;
kinc_g5_command_list_set_vertex_buffers(&commandList, current_state.vertex_buffers, current_state.vertex_buffer_offsets, count);
}
int kinc_internal_g4_vertex_buffer_set(kinc_g4_vertex_buffer_t *buffer, int offset) {
kinc_g4_vertex_buffer_t *buffers[1];
buffers[0] = buffer;
kinc_g4_set_vertex_buffers(buffers, 1);
return 0;
}
void kinc_g4_set_index_buffer(kinc_g4_index_buffer_t *buffer) {
kinc_g5_index_buffer_t *g5_index_buffer = &buffer->impl._buffer;
current_state.index_buffer = g5_index_buffer;
kinc_g5_command_list_set_index_buffer(&commandList, g5_index_buffer);
}
#ifdef KINC_KONG
void kinc_g4_set_texture(uint32_t unit, kinc_g4_texture_t *texture) {
if (!texture->impl._uploaded) {
kinc_g5_command_list_upload_texture(&commandList, &texture->impl._texture);
texture->impl._uploaded = true;
}
assert(KINC_G4_SHADER_TYPE_COUNT == KINC_G5_SHADER_TYPE_COUNT);
kinc_g5_texture_unit_t g5_unit = {0};
for (int i = 0; i < KINC_G5_SHADER_TYPE_COUNT; ++i) {
g5_unit.stages[i] = unit;
}
bool found = false;
for (int i = 0; i < current_state.texture_count; ++i) {
if (kinc_g5_texture_unit_equals(&current_state.texture_units[i], &g5_unit)) {
current_state.textures[i] = &texture->impl._texture;
current_state.texture_units[i] = g5_unit;
found = true;
break;
}
}
if (!found) {
assert(current_state.texture_count < MAX_TEXTURES);
current_state.textures[current_state.texture_count] = &texture->impl._texture;
current_state.texture_units[current_state.texture_count] = g5_unit;
current_state.texture_count += 1;
}
kinc_g5_command_list_set_texture(&commandList, g5_unit, &texture->impl._texture);
}
#else
void kinc_g4_set_texture(kinc_g4_texture_unit_t unit, kinc_g4_texture_t *texture) {
if (!texture->impl._uploaded) {
kinc_g5_command_list_upload_texture(&commandList, &texture->impl._texture);
texture->impl._uploaded = true;
}
assert(KINC_G4_SHADER_TYPE_COUNT == KINC_G5_SHADER_TYPE_COUNT);
kinc_g5_texture_unit_t g5_unit;
memcpy(&g5_unit.stages[0], &unit.stages[0], KINC_G5_SHADER_TYPE_COUNT * sizeof(int));
bool found = false;
for (int i = 0; i < current_state.texture_count; ++i) {
if (kinc_g5_texture_unit_equals(&current_state.texture_units[i], &g5_unit)) {
current_state.textures[i] = &texture->impl._texture;
current_state.texture_units[i] = g5_unit;
found = true;
break;
}
}
if (!found) {
assert(current_state.texture_count < MAX_TEXTURES);
current_state.textures[current_state.texture_count] = &texture->impl._texture;
current_state.texture_units[current_state.texture_count] = g5_unit;
current_state.texture_count += 1;
}
kinc_g5_command_list_set_texture(&commandList, g5_unit, &texture->impl._texture);
}
#endif
void kinc_g4_set_image_texture(kinc_g4_texture_unit_t unit, kinc_g4_texture_t *texture) {}
int kinc_g4_max_bound_textures(void) {
return kinc_g5_max_bound_textures();
}
bool kinc_g4_init_occlusion_query(unsigned *occlusionQuery) {
return kinc_g5_command_list_init_occlusion_query(&commandList, occlusionQuery);
}
void kinc_g4_delete_occlusion_query(unsigned occlusionQuery) {
kinc_g5_command_list_delete_occlusion_query(&commandList, occlusionQuery);
}
bool kinc_g4_are_query_results_available(unsigned occlusionQuery) {
return kinc_g5_command_list_are_query_results_available(&commandList, occlusionQuery);
}
void kinc_g4_get_query_result(unsigned occlusionQuery, unsigned *pixelCount) {
kinc_g5_command_list_get_query_result(&commandList, occlusionQuery, pixelCount);
}
void kinc_g4_set_pipeline(kinc_g4_pipeline_t *pipeline) {
kinc_g5_pipeline_t *g5_pipeline = &pipeline->impl._pipeline;
current_state.pipeline = g5_pipeline;
kinc_g5_command_list_set_pipeline(&commandList, g5_pipeline);
}
void kinc_g4_set_blend_constant(float r, float g, float b, float a) {
current_state.blend_constant_set = true;
current_state.blend_constant_r = r;
current_state.blend_constant_g = g;
current_state.blend_constant_b = b;
current_state.blend_constant_a = a;
kinc_g5_command_list_set_blend_constant(&commandList, r, g, b, a);
}
void kinc_g4_set_texture_array(kinc_g4_texture_unit_t unit, struct kinc_g4_texture_array *array) {}
bool kinc_g4_supports_instanced_rendering(void) {
return kinc_g5_supports_instanced_rendering();
}
bool kinc_g4_supports_compute_shaders(void) {
return kinc_g5_supports_compute_shaders();
}
bool kinc_g4_supports_blend_constants(void) {
return kinc_g5_supports_blend_constants();
}
bool kinc_g4_supports_non_pow2_textures(void) {
return kinc_g5_supports_non_pow2_textures();
}
bool kinc_g4_render_targets_inverted_y(void) {
return kinc_g5_render_targets_inverted_y();
}
#ifdef KINC_KONG
void kinc_g4_render_target_use_color_as_texture(kinc_g4_render_target_t *render_target, uint32_t unit) {
if (render_target->impl.state != KINC_INTERNAL_RENDER_TARGET_STATE_TEXTURE) {
kinc_g5_command_list_render_target_to_texture_barrier(&commandList, &render_target->impl._renderTarget);
render_target->impl.state = KINC_INTERNAL_RENDER_TARGET_STATE_TEXTURE;
}
assert(KINC_G4_SHADER_TYPE_COUNT == KINC_G5_SHADER_TYPE_COUNT);
kinc_g5_texture_unit_t g5_unit = {0};
for (int i = 0; i < KINC_G5_SHADER_TYPE_COUNT; ++i) {
g5_unit.stages[i] = unit;
}
bool found = false;
for (int i = 0; i < current_state.render_target_count; ++i) {
if (kinc_g5_texture_unit_equals(&current_state.render_target_units[i], &g5_unit)) {
current_state.render_targets[i] = &render_target->impl._renderTarget;
current_state.render_target_units[i] = g5_unit;
found = true;
break;
}
}
if (!found) {
assert(current_state.render_target_count < MAX_TEXTURES);
current_state.render_targets[current_state.render_target_count] = &render_target->impl._renderTarget;
current_state.render_target_units[current_state.render_target_count] = g5_unit;
current_state.render_target_count += 1;
}
kinc_g5_command_list_set_texture_from_render_target(&commandList, g5_unit, &render_target->impl._renderTarget);
}
#else
void kinc_g4_render_target_use_color_as_texture(kinc_g4_render_target_t *render_target, kinc_g4_texture_unit_t unit) {
if (render_target->impl.state != KINC_INTERNAL_RENDER_TARGET_STATE_TEXTURE) {
kinc_g5_command_list_render_target_to_texture_barrier(&commandList, &render_target->impl._renderTarget);
render_target->impl.state = KINC_INTERNAL_RENDER_TARGET_STATE_TEXTURE;
}
assert(KINC_G4_SHADER_TYPE_COUNT == KINC_G5_SHADER_TYPE_COUNT);
kinc_g5_texture_unit_t g5_unit;
memcpy(&g5_unit.stages[0], &unit.stages[0], KINC_G5_SHADER_TYPE_COUNT * sizeof(int));
bool found = false;
for (int i = 0; i < current_state.render_target_count; ++i) {
if (kinc_g5_texture_unit_equals(&current_state.render_target_units[i], &g5_unit)) {
current_state.render_targets[i] = &render_target->impl._renderTarget;
current_state.render_target_units[i] = g5_unit;
found = true;
break;
}
}
if (!found) {
assert(current_state.render_target_count < MAX_TEXTURES);
current_state.render_targets[current_state.render_target_count] = &render_target->impl._renderTarget;
current_state.render_target_units[current_state.render_target_count] = g5_unit;
current_state.render_target_count += 1;
}
kinc_g5_command_list_set_texture_from_render_target(&commandList, g5_unit, &render_target->impl._renderTarget);
}
#endif
void kinc_g4_render_target_use_depth_as_texture(kinc_g4_render_target_t *render_target, kinc_g4_texture_unit_t unit) {
if (render_target->impl.state != KINC_INTERNAL_RENDER_TARGET_STATE_TEXTURE) {
kinc_g5_command_list_render_target_to_texture_barrier(&commandList, &render_target->impl._renderTarget);
render_target->impl.state = KINC_INTERNAL_RENDER_TARGET_STATE_TEXTURE;
}
assert(KINC_G4_SHADER_TYPE_COUNT == KINC_G5_SHADER_TYPE_COUNT);
kinc_g5_texture_unit_t g5_unit;
memcpy(&g5_unit.stages[0], &unit.stages[0], KINC_G5_SHADER_TYPE_COUNT * sizeof(int));
bool found = false;
for (int i = 0; i < current_state.depth_render_target_count; ++i) {
if (kinc_g5_texture_unit_equals(&current_state.depth_render_target_units[i], &g5_unit)) {
current_state.depth_render_targets[i] = &render_target->impl._renderTarget;
current_state.depth_render_target_units[i] = g5_unit;
found = true;
break;
}
}
if (!found) {
assert(current_state.depth_render_target_count < MAX_TEXTURES);
current_state.depth_render_targets[current_state.depth_render_target_count] = &render_target->impl._renderTarget;
current_state.depth_render_target_units[current_state.depth_render_target_count] = g5_unit;
current_state.depth_render_target_count += 1;
}
kinc_g5_command_list_set_texture_from_render_target_depth(&commandList, g5_unit, &render_target->impl._renderTarget);
}
#ifdef KINC_KONG
void kinc_g4_set_constant_buffer(uint32_t id, struct kinc_g4_constant_buffer *buffer) {
kinc_g5_command_list_set_vertex_constant_buffer(&commandList, &buffer->impl.buffer, 0, kinc_g5_constant_buffer_size(&buffer->impl.buffer));
}
#endif

View File

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

View File

@ -0,0 +1,35 @@
#ifdef KINC_KONG
#include <kinc/graphics4/constantbuffer.h>
void kinc_g4_constant_buffer_init(kinc_g4_constant_buffer *buffer, size_t size) {
kinc_g5_constant_buffer_init(&buffer->impl.buffer, (int)size);
}
void kinc_g4_constant_buffer_destroy(kinc_g4_constant_buffer *buffer) {
kinc_g5_constant_buffer_destroy(&buffer->impl.buffer);
}
uint8_t *kinc_g4_constant_buffer_lock_all(kinc_g4_constant_buffer *buffer) {
kinc_g5_constant_buffer_lock_all(&buffer->impl.buffer);
return buffer->impl.buffer.data;
}
uint8_t *kinc_g4_constant_buffer_lock(kinc_g4_constant_buffer *buffer, size_t start, size_t size) {
kinc_g5_constant_buffer_lock(&buffer->impl.buffer, (int)start, (int)size);
return buffer->impl.buffer.data;
}
void kinc_g4_constant_buffer_unlock_all(kinc_g4_constant_buffer *buffer) {
kinc_g5_constant_buffer_unlock(&buffer->impl.buffer);
}
void kinc_g4_constant_buffer_unlock(kinc_g4_constant_buffer *buffer, size_t count) {
kinc_g5_constant_buffer_unlock(&buffer->impl.buffer);
}
size_t kinc_g4_constant_buffer_size(kinc_g4_constant_buffer *buffer) {
return kinc_g5_constant_buffer_size(&buffer->impl.buffer);
}
#endif

View File

@ -0,0 +1,11 @@
#pragma once
#ifdef KINC_KONG
#include <kinc/graphics5/constantbuffer.h>
typedef struct kinc_g4_constant_buffer_impl {
kinc_g5_constant_buffer_t buffer;
} kinc_g4_constant_buffer_impl;
#endif

View File

@ -0,0 +1,11 @@
#include "samplers.c.h"
#include "G4.c.h"
#include "constantbuffer.c.h"
#include "indexbuffer.c.h"
#include "pipeline.c.h"
#include "rendertarget.c.h"
#include "shader.c.h"
#include "texture.c.h"
#include "texturearray.c.h"
#include "vertexbuffer.c.h"

View File

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

View File

@ -0,0 +1,35 @@
#include <kinc/graphics4/indexbuffer.h>
#include <kinc/graphics5/commandlist.h>
extern kinc_g5_command_list_t commandList;
void kinc_g4_index_buffer_init(kinc_g4_index_buffer_t *buffer, int count, kinc_g4_index_buffer_format_t format, kinc_g4_usage_t usage) {
kinc_g5_index_buffer_init(&buffer->impl._buffer, count, (kinc_g5_index_buffer_format_t)format, usage == KINC_G4_USAGE_STATIC);
}
void kinc_g4_index_buffer_destroy(kinc_g4_index_buffer_t *buffer) {
kinc_g5_index_buffer_destroy(&buffer->impl._buffer);
}
void *kinc_g4_index_buffer_lock_all(kinc_g4_index_buffer_t *buffer) {
return kinc_g5_index_buffer_lock_all(&buffer->impl._buffer);
}
void *kinc_g4_index_buffer_lock(kinc_g4_index_buffer_t *buffer, int start, int count) {
return kinc_g5_index_buffer_lock(&buffer->impl._buffer, start, count);
}
void kinc_g4_index_buffer_unlock_all(kinc_g4_index_buffer_t *buffer) {
kinc_g5_index_buffer_unlock_all(&buffer->impl._buffer);
kinc_g5_command_list_upload_index_buffer(&commandList, &buffer->impl._buffer);
}
void kinc_g4_index_buffer_unlock(kinc_g4_index_buffer_t *buffer, int count) {
kinc_g5_index_buffer_unlock(&buffer->impl._buffer, count);
kinc_g5_command_list_upload_index_buffer(&commandList, &buffer->impl._buffer);
}
int kinc_g4_index_buffer_count(kinc_g4_index_buffer_t *buffer) {
return kinc_g5_index_buffer_count(&buffer->impl._buffer);
}

View File

@ -0,0 +1,15 @@
#pragma once
#include <kinc/graphics5/indexbuffer.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
kinc_g5_index_buffer_t _buffer;
} kinc_g4_index_buffer_impl_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,64 @@
#include <kinc/backend/graphics4/pipeline.h>
#include <kinc/graphics4/pipeline.h>
#include <kinc/graphics4/shader.h>
#include <kinc/graphics5/pipeline.h>
void kinc_g4_pipeline_init(kinc_g4_pipeline_t *pipe) {
kinc_g4_internal_pipeline_set_defaults(pipe);
kinc_g5_pipeline_init(&pipe->impl._pipeline);
}
void kinc_g4_pipeline_destroy(kinc_g4_pipeline_t *pipe) {
kinc_g5_pipeline_destroy(&pipe->impl._pipeline);
}
#ifndef KINC_KONG
kinc_g4_constant_location_t kinc_g4_pipeline_get_constant_location(kinc_g4_pipeline_t *pipe, const char *name) {
kinc_g4_constant_location_t location;
location.impl._location = kinc_g5_pipeline_get_constant_location(&pipe->impl._pipeline, name);
return location;
}
kinc_g4_texture_unit_t kinc_g4_pipeline_get_texture_unit(kinc_g4_pipeline_t *pipe, const char *name) {
kinc_g5_texture_unit_t g5_unit = kinc_g5_pipeline_get_texture_unit(&pipe->impl._pipeline, name);
assert(KINC_G4_SHADER_TYPE_COUNT == KINC_G5_SHADER_TYPE_COUNT);
kinc_g4_texture_unit_t g4_unit;
memcpy(&g4_unit.stages[0], &g5_unit.stages[0], KINC_G4_SHADER_TYPE_COUNT * sizeof(int));
return g4_unit;
}
#endif
void kinc_g4_pipeline_compile(kinc_g4_pipeline_t *pipe) {
for (int i = 0; i < 16; ++i) {
pipe->impl._pipeline.inputLayout[i] = pipe->input_layout[i];
}
pipe->impl._pipeline.vertexShader = &pipe->vertex_shader->impl._shader;
pipe->impl._pipeline.fragmentShader = &pipe->fragment_shader->impl._shader;
pipe->impl._pipeline.geometryShader = pipe->geometry_shader != NULL ? &pipe->geometry_shader->impl._shader : NULL;
pipe->impl._pipeline.tessellationControlShader = pipe->tessellation_control_shader != NULL ? &pipe->tessellation_control_shader->impl._shader : NULL;
pipe->impl._pipeline.tessellationEvaluationShader =
pipe->tessellation_evaluation_shader != NULL ? &pipe->tessellation_evaluation_shader->impl._shader : NULL;
pipe->impl._pipeline.blend_source = (kinc_g5_blending_factor_t)pipe->blend_source;
pipe->impl._pipeline.blend_destination = (kinc_g5_blending_factor_t)pipe->blend_destination;
pipe->impl._pipeline.blend_operation = (kinc_g5_blending_operation_t)pipe->blend_operation;
pipe->impl._pipeline.alpha_blend_source = (kinc_g5_blending_factor_t)pipe->alpha_blend_source;
pipe->impl._pipeline.alpha_blend_destination = (kinc_g5_blending_factor_t)pipe->alpha_blend_destination;
pipe->impl._pipeline.alpha_blend_operation = (kinc_g5_blending_operation_t)pipe->alpha_blend_operation;
pipe->impl._pipeline.cullMode = (kinc_g5_cull_mode_t)pipe->cull_mode;
pipe->impl._pipeline.depthMode = (kinc_g5_compare_mode_t)pipe->depth_mode;
pipe->impl._pipeline.depthWrite = pipe->depth_write;
pipe->impl._pipeline.colorAttachmentCount = pipe->color_attachment_count;
for (int i = 0; i < 8; ++i) {
pipe->impl._pipeline.colorWriteMaskRed[i] = pipe->color_write_mask_red[i];
pipe->impl._pipeline.colorWriteMaskGreen[i] = pipe->color_write_mask_green[i];
pipe->impl._pipeline.colorWriteMaskBlue[i] = pipe->color_write_mask_blue[i];
pipe->impl._pipeline.colorWriteMaskAlpha[i] = pipe->color_write_mask_alpha[i];
pipe->impl._pipeline.colorAttachment[i] = (kinc_g5_render_target_format_t)pipe->color_attachment[i];
}
pipe->impl._pipeline.depthAttachmentBits = pipe->depth_attachment_bits;
pipe->impl._pipeline.stencilAttachmentBits = pipe->stencil_attachment_bits;
kinc_g5_pipeline_compile(&pipe->impl._pipeline);
}

View File

@ -0,0 +1,25 @@
#pragma once
#include <kinc/graphics5/constantlocation.h>
#include <kinc/graphics5/pipeline.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
// PipelineStateImpl();
kinc_g5_pipeline_t _pipeline;
} kinc_g4_pipeline_impl_t;
typedef struct {
kinc_g5_constant_location_t _location;
} kinc_g4_constant_location_impl_t;
typedef struct {
int nothing;
} Kinc_G4_AttributeLocationImpl;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,36 @@
#include <kinc/backend/graphics4/rendertarget.h>
#include <kinc/graphics4/rendertarget.h>
#include <kinc/graphics5/commandlist.h>
#include <kinc/log.h>
extern kinc_g5_command_list_t commandList;
void kinc_g4_render_target_init_with_multisampling(kinc_g4_render_target_t *render_target, int width, int height, kinc_g4_render_target_format_t format,
int depthBufferBits, int stencilBufferBits, int samples_per_pixel) {
kinc_g5_render_target_init_with_multisampling(&render_target->impl._renderTarget, width, height, (kinc_g5_render_target_format_t)format, depthBufferBits,
stencilBufferBits, samples_per_pixel);
render_target->texWidth = render_target->width = width;
render_target->texHeight = render_target->height = height;
render_target->impl.state = KINC_INTERNAL_RENDER_TARGET_STATE_RENDER_TARGET;
}
void kinc_g4_render_target_init_cube_with_multisampling(kinc_g4_render_target_t *render_target, int cubeMapSize, kinc_g4_render_target_format_t format,
int depthBufferBits, int stencilBufferBits, int samples_per_pixel) {
kinc_g5_render_target_init_cube_with_multisampling(&render_target->impl._renderTarget, cubeMapSize, (kinc_g5_render_target_format_t)format, depthBufferBits,
stencilBufferBits, samples_per_pixel);
}
void kinc_g4_render_target_destroy(kinc_g4_render_target_t *render_target) {
kinc_g5_render_target_destroy(&render_target->impl._renderTarget);
}
void kinc_g4_render_target_set_depth_stencil_from(kinc_g4_render_target_t *render_target, kinc_g4_render_target_t *source) {
kinc_g5_render_target_set_depth_stencil_from(&render_target->impl._renderTarget, &source->impl._renderTarget);
}
void kinc_g4_render_target_get_pixels(kinc_g4_render_target_t *render_target, uint8_t *data) {
kinc_g5_command_list_get_render_target_pixels(&commandList, &render_target->impl._renderTarget, data);
}
void kinc_g4_render_target_generate_mipmaps(kinc_g4_render_target_t *render_target, int levels) {}

View File

@ -0,0 +1,21 @@
#pragma once
#include <kinc/graphics5/rendertarget.h>
#ifdef __cplusplus
extern "C" {
#endif
enum kinc_internal_render_target_state { KINC_INTERNAL_RENDER_TARGET_STATE_RENDER_TARGET, KINC_INTERNAL_RENDER_TARGET_STATE_TEXTURE };
typedef struct {
// RenderTargetImpl(int width, int height, int depthBufferBits, bool antialiasing, Graphics5::RenderTargetFormat format, int stencilBufferBits,
// int contextId);
// RenderTargetImpl(int cubeMapSize, int depthBufferBits, bool antialiasing, Graphics5::RenderTargetFormat format, int stencilBufferBits, int contextId);
kinc_g5_render_target_t _renderTarget;
enum kinc_internal_render_target_state state;
} kinc_g4_render_target_impl_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,50 @@
#include <kinc/graphics5/sampler.h>
#include <assert.h>
#define MAX_SAMPLERS_PER_STAGE 16
static kinc_g5_sampler_options_t sampler_options[KINC_G5_SHADER_TYPE_COUNT][MAX_SAMPLERS_PER_STAGE];
static void samplers_reset(void) {
for (int i = 0; i < KINC_G5_SHADER_TYPE_COUNT; ++i) {
for (int j = 0; j < MAX_SAMPLERS_PER_STAGE; ++j) {
kinc_g5_sampler_options_set_defaults(&sampler_options[i][j]);
}
}
}
bool sampler_options_equals(kinc_g5_sampler_options_t *options1, kinc_g5_sampler_options_t *options2) {
return options1->u_addressing == options2->u_addressing && options1->v_addressing == options2->v_addressing &&
options1->w_addressing == options2->w_addressing && options1->minification_filter == options2->minification_filter &&
options1->magnification_filter == options2->magnification_filter && options1->mipmap_filter == options2->mipmap_filter &&
options1->lod_min_clamp == options2->lod_min_clamp && options1->lod_max_clamp == options2->lod_max_clamp &&
options1->max_anisotropy == options2->max_anisotropy && options1->is_comparison == options2->is_comparison &&
options1->compare_mode == options2->compare_mode;
}
struct sampler_cache_entry {
kinc_g5_sampler_options_t options;
kinc_g5_sampler_t sampler;
};
#define MAX_SAMPLER_CACHE_SIZE 256
static struct sampler_cache_entry sampler_cache[MAX_SAMPLER_CACHE_SIZE];
static int sampler_cache_size = 0;
// TODO: Please make this much faster
static kinc_g5_sampler_t *get_current_sampler(int stage, int unit) {
for (int i = 0; i < sampler_cache_size; ++i) {
if (sampler_options_equals(&sampler_cache[i].options, &sampler_options[stage][unit])) {
return &sampler_cache[i].sampler;
}
}
assert(sampler_cache_size < MAX_SAMPLER_CACHE_SIZE);
kinc_g5_sampler_t *sampler = &sampler_cache[sampler_cache_size].sampler;
kinc_g5_sampler_init(sampler, &sampler_options[stage][unit]);
sampler_cache[sampler_cache_size].options = sampler_options[stage][unit];
sampler_cache_size += 1;
return sampler;
}

View File

@ -0,0 +1,49 @@
#include <kinc/graphics4/shader.h>
void kinc_g4_shader_init(kinc_g4_shader_t *shader, const void *_data, size_t length, kinc_g4_shader_type_t type) {
kinc_g5_shader_init(&shader->impl._shader, _data, length, (kinc_g5_shader_type_t)type);
}
#ifdef KRAFIX_LIBRARY
extern int krafix_compile(const char *source, char *output, int *length, const char *targetlang, const char *system, const char *shadertype, int version);
#endif
int kinc_g4_shader_init_from_source(kinc_g4_shader_t *shader, const char *source, kinc_g4_shader_type_t type) {
#ifdef KRAFIX_LIBRARY
char *output = malloc(1024 * 1024);
int length;
#ifdef KINC_WINDOWS
const char *system = "windows";
#elif defined(KINC_MACOS)
const char *system = "macos";
#elif defined(KINC_LINUX)
const char *system = "linux";
#elif defined(KINC_ANDROID)
const char *system = "android";
#elif defined(KINC_IOS)
const char *system = "ios";
#endif
#ifdef KORE_VULKAN
const char *target = "spirv";
#elif defined(KORE_METAL)
const char *target = "metal";
#else
const char *target = "d3d11";
#endif
int errors = krafix_compile(source, output, &length, target, system, type == KINC_G4_SHADER_TYPE_FRAGMENT ? "frag" : "vert", -1);
if (errors > 0) {
return errors;
}
kinc_g4_shader_init(shader, output, length, type);
return 0;
#else
return 0;
#endif
}
void kinc_g4_shader_destroy(kinc_g4_shader_t *shader) {
kinc_g5_shader_destroy(&shader->impl._shader);
}

View File

@ -0,0 +1,16 @@
#pragma once
#include <kinc/graphics5/shader.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
// ShaderImpl(void *data, int length, Graphics5::ShaderType type);
kinc_g5_shader_t _shader;
} kinc_g4_shader_impl_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,70 @@
#include <kinc/graphics4/graphics.h>
#include <kinc/graphics4/texture.h>
#include <kinc/graphics5/texture.h>
#include <kinc/io/filereader.h>
#include <kinc/backend/graphics4/texture.h>
void kinc_g4_texture_init_from_image(kinc_g4_texture_t *texture, kinc_image_t *image) {
texture->impl._uploaded = false;
kinc_g5_texture_init_from_image(&texture->impl._texture, image);
texture->tex_width = texture->impl._texture.texWidth;
texture->tex_height = texture->impl._texture.texHeight;
texture->tex_depth = 1;
texture->format = image->format;
}
void kinc_g4_texture_init_from_image3d(kinc_g4_texture_t *texture, kinc_image_t *image) {}
void kinc_g4_texture_init(kinc_g4_texture_t *texture, int width, int height, kinc_image_format_t format) {
texture->impl._uploaded = true;
kinc_g5_texture_init(&texture->impl._texture, width, height, format);
texture->tex_width = texture->impl._texture.texWidth;
texture->tex_height = texture->impl._texture.texHeight;
texture->tex_depth = 1;
texture->format = format;
}
void kinc_g4_texture_init3d(kinc_g4_texture_t *texture, int width, int height, int depth, kinc_image_format_t format) {}
void kinc_g4_texture_init_from_bytes(kinc_g4_texture_t *texture, void *data, int size, const char *format) {}
void kinc_g4_texture_init_from_bytes3d(kinc_g4_texture_t *texture, void *data, int width, int height, int depth, int format, bool readable) {}
void kinc_g4_texture_destroy(kinc_g4_texture_t *texture) {
// kinc_g4_internal_texture_unset(texture);
kinc_g5_texture_destroy(&texture->impl._texture);
}
void kinc_g4_internal_texture_unset(kinc_g4_texture_t *texture) {
// TODO
}
void kinc_g4_internal_texture_unmipmap(kinc_g4_texture_t *texture) {
// TODO
}
uint8_t *kinc_g4_texture_lock(kinc_g4_texture_t *texture) {
return kinc_g5_texture_lock(&texture->impl._texture);
}
void kinc_g4_texture_unlock(kinc_g4_texture_t *texture) {
kinc_g5_texture_unlock(&texture->impl._texture);
texture->impl._uploaded = false;
}
void kinc_g4_texture_clear(kinc_g4_texture_t *texture, int x, int y, int z, int width, int height, int depth, unsigned color) {
kinc_g5_texture_clear(&texture->impl._texture, x, y, z, width, height, depth, color);
}
int kinc_g4_texture_stride(kinc_g4_texture_t *texture) {
return kinc_g5_texture_stride(&texture->impl._texture);
}
void kinc_g4_texture_generate_mipmaps(kinc_g4_texture_t *texture, int levels) {
kinc_g5_texture_generate_mipmaps(&texture->impl._texture, levels);
}
void kinc_g4_texture_set_mipmap(kinc_g4_texture_t *texture, kinc_image_t *mipmap, int level) {
kinc_g5_texture_set_mipmap(&texture->impl._texture, mipmap, level);
}

View File

@ -0,0 +1,29 @@
#pragma once
#include <kinc/graphics5/texture.h>
#include <kinc/graphics5/textureunit.h>
#include <kinc/image.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
kinc_g5_texture_unit_t _unit;
} kinc_g4_texture_unit_impl_t;
typedef struct {
/*TextureImpl();
TextureImpl(int width, int height, Image::Format format, bool readable);
TextureImpl(int width, int height, int depth, Image::Format format, bool readable);
~TextureImpl();
void unmipmap();
void unset();*/
kinc_g5_texture_t _texture;
bool _uploaded;
} kinc_g4_texture_impl_t;
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,7 @@
#include <kinc/graphics4/texturearray.h>
void kinc_g4_texture_array_init(kinc_g4_texture_array_t *array, kinc_image_t *textures, int count) {}
void kinc_g4_texture_array_destroy(kinc_g4_texture_array_t *array) {}
// void TextureArrayImpl::set(TextureUnit unit) {}

View File

@ -0,0 +1,14 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
// void set(Kore::Graphics4::TextureUnit unit);
int nothing;
} kinc_g4_texture_array_impl_t;
#ifdef __cplusplus
}
#endif

Some files were not shown because too many files have changed in this diff Show More