Merge pull request 'Update Files' (#1) from Onek8/LeenkxCore:main into main
Reviewed-on: LeenkxTeam/LeenkxCore#1
This commit is contained in:
commit
a678b57d7f
0
Deployment/.keepme
Normal file
0
Deployment/.keepme
Normal file
11
Deployment/g1.frag
Normal file
11
Deployment/g1.frag
Normal 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
12
Deployment/g1.vert
Normal 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
84
Kinc/.clang-format
Normal 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
2
Kinc/.clangd
Normal file
@ -0,0 +1,2 @@
|
||||
CompileFlags:
|
||||
Add: [-D,KINC_EDITOR_SUPPORT, -Wall]
|
@ -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;
|
||||
}
|
||||
}
|
296
Kinc/Backends/Audio2/WASAPI/Sources/kinc/backend/wasapi.c
Normal file
296
Kinc/Backends/Audio2/WASAPI/Sources/kinc/backend/wasapi.c
Normal 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)
|
||||
}
|
@ -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)
|
||||
}
|
62
Kinc/Backends/Audio3/A3onA2/Sources/kinc/backend/Audio.cpp
Normal file
62
Kinc/Backends/Audio3/A3onA2/Sources/kinc/backend/Audio.cpp
Normal 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;
|
||||
}
|
@ -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
|
2261
Kinc/Backends/Graphics3/OpenGL1/Sources/GL/eglew.h
Normal file
2261
Kinc/Backends/Graphics3/OpenGL1/Sources/GL/eglew.h
Normal file
File diff suppressed because it is too large
Load Diff
23953
Kinc/Backends/Graphics3/OpenGL1/Sources/GL/glew.c
Normal file
23953
Kinc/Backends/Graphics3/OpenGL1/Sources/GL/glew.c
Normal file
File diff suppressed because it is too large
Load Diff
20113
Kinc/Backends/Graphics3/OpenGL1/Sources/GL/glew.h
Normal file
20113
Kinc/Backends/Graphics3/OpenGL1/Sources/GL/glew.h
Normal file
File diff suppressed because it is too large
Load Diff
1769
Kinc/Backends/Graphics3/OpenGL1/Sources/GL/glxew.h
Normal file
1769
Kinc/Backends/Graphics3/OpenGL1/Sources/GL/glxew.h
Normal file
File diff suppressed because it is too large
Load Diff
1427
Kinc/Backends/Graphics3/OpenGL1/Sources/GL/wglew.h
Normal file
1427
Kinc/Backends/Graphics3/OpenGL1/Sources/GL/wglew.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
}
|
@ -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;
|
||||
};
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "IndexBufferImpl.h"
|
||||
#include "RenderTargetImpl.h"
|
||||
#include "TextureImpl.h"
|
||||
#include "VertexBufferImpl.h"
|
@ -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;
|
||||
}
|
@ -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;
|
||||
};
|
||||
}
|
@ -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);
|
||||
}
|
@ -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;
|
||||
};
|
||||
}
|
1073
Kinc/Backends/Graphics3/OpenGL1/Sources/kinc/backend/OpenGL.cpp
Normal file
1073
Kinc/Backends/Graphics3/OpenGL1/Sources/kinc/backend/OpenGL.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <Kore/Graphics1/Image.h>
|
||||
#include <Kore/Graphics3/Graphics.h>
|
||||
#include <Kore/Math/Matrix.h>
|
@ -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;
|
||||
}
|
@ -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;
|
||||
};
|
||||
}
|
@ -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);
|
||||
}
|
@ -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);
|
||||
};
|
||||
}
|
@ -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) {}
|
@ -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;
|
||||
};
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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();
|
||||
};
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
};
|
||||
}
|
75
Kinc/Backends/Graphics3/OpenGL1/Sources/kinc/backend/ogl.h
Normal file
75
Kinc/Backends/Graphics3/OpenGL1/Sources/kinc/backend/ogl.h
Normal 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__); \
|
||||
} \
|
||||
}
|
@ -0,0 +1,491 @@
|
||||
#ifdef KORE_OCULUS
|
||||
|
||||
#include <kinc/vr/vrinterface.h>
|
||||
|
||||
#include "Direct3D11.h"
|
||||
#include <Kore/Graphics4/Graphics.h>
|
||||
#include <kinc/log.h>
|
||||
|
||||
#include "OVR_CAPI_D3D.h"
|
||||
|
||||
#include "d3d11.h"
|
||||
#include <vector>
|
||||
#if _MSC_VER > 1600
|
||||
#include "DirectXMath.h"
|
||||
using namespace DirectX;
|
||||
#else
|
||||
#include "xnamath.h"
|
||||
#endif //_MSC_VER > 1600
|
||||
|
||||
#pragma comment(lib, "dxgi.lib")
|
||||
#pragma comment(lib, "d3d11.lib")
|
||||
#pragma comment(lib, "d3dcompiler.lib")
|
||||
|
||||
using namespace Kore;
|
||||
|
||||
namespace {
|
||||
kinc_vr_sensor_state_t sensorStates[2];
|
||||
}
|
||||
|
||||
//------------------------------------------------------------
|
||||
struct DepthBuffer {
|
||||
ID3D11DepthStencilView *TexDsv;
|
||||
|
||||
DepthBuffer(ID3D11Device *Device, int sizeW, int sizeH, int sampleCount = 1) {
|
||||
DXGI_FORMAT format = DXGI_FORMAT_D32_FLOAT;
|
||||
D3D11_TEXTURE2D_DESC dsDesc;
|
||||
dsDesc.Width = sizeW;
|
||||
dsDesc.Height = sizeH;
|
||||
dsDesc.MipLevels = 1;
|
||||
dsDesc.ArraySize = 1;
|
||||
dsDesc.Format = format;
|
||||
dsDesc.SampleDesc.Count = sampleCount;
|
||||
dsDesc.SampleDesc.Quality = 0;
|
||||
dsDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
dsDesc.CPUAccessFlags = 0;
|
||||
dsDesc.MiscFlags = 0;
|
||||
dsDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
|
||||
ID3D11Texture2D *Tex;
|
||||
Device->CreateTexture2D(&dsDesc, nullptr, &Tex);
|
||||
Device->CreateDepthStencilView(Tex, nullptr, &TexDsv);
|
||||
Tex->Release();
|
||||
}
|
||||
~DepthBuffer() {
|
||||
TexDsv->Release();
|
||||
TexDsv = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------
|
||||
struct Camera {
|
||||
XMVECTOR Pos;
|
||||
XMVECTOR Rot;
|
||||
Camera(){};
|
||||
Camera(XMVECTOR *pos, XMVECTOR *rot) : Pos(*pos), Rot(*rot){};
|
||||
Camera(const XMVECTOR &pos, const XMVECTOR &rot) : Pos(pos), Rot(rot){};
|
||||
XMMATRIX GetViewMatrix() {
|
||||
XMVECTOR forward = XMVector3Rotate(XMVectorSet(0, 0, -1, 0), Rot);
|
||||
return (XMMatrixLookAtRH(Pos, XMVectorAdd(Pos, forward), XMVector3Rotate(XMVectorSet(0, 1, 0, 0), Rot)));
|
||||
}
|
||||
|
||||
static void *operator new(std::size_t size) {
|
||||
UNREFERENCED_PARAMETER(size);
|
||||
return _aligned_malloc(sizeof(Camera), __alignof(Camera));
|
||||
}
|
||||
|
||||
static void operator delete(void *p) {
|
||||
_aligned_free(p);
|
||||
}
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
struct DirectX11 {
|
||||
HWND Window;
|
||||
bool Running;
|
||||
int WinSizeW;
|
||||
int WinSizeH;
|
||||
|
||||
HINSTANCE hInstance;
|
||||
|
||||
DirectX11() : Window(nullptr), Running(false), WinSizeW(0), WinSizeH(0), hInstance(nullptr) {}
|
||||
|
||||
~DirectX11() {
|
||||
ReleaseDevice();
|
||||
CloseWindow();
|
||||
}
|
||||
|
||||
bool InitWindow(HINSTANCE hinst, const char *title, const char *windowClassName) {
|
||||
hInstance = hinst;
|
||||
Running = true;
|
||||
|
||||
// Adjust the window size and show at InitDevice time
|
||||
wchar_t wchTitle[256];
|
||||
MultiByteToWideChar(CP_ACP, 0, title, -1, wchTitle, 256);
|
||||
wchar_t wchClassName[256];
|
||||
MultiByteToWideChar(CP_ACP, 0, windowClassName, -1, wchClassName, 256);
|
||||
Window = CreateWindowW(wchClassName, wchTitle, WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, 0, 0, hinst, 0);
|
||||
if (!Window)
|
||||
return false;
|
||||
|
||||
SetWindowLongPtr(Window, 0, LONG_PTR(this));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CloseWindow() {
|
||||
if (Window) {
|
||||
Window = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool InitDevice(int vpW, int vpH, const LUID *pLuid, bool windowed = true, int scale = 1) {
|
||||
WinSizeW = vpW;
|
||||
WinSizeH = vpH;
|
||||
|
||||
if (scale == 0)
|
||||
scale = 1;
|
||||
|
||||
RECT size = {0, 0, vpW / scale, vpH / scale};
|
||||
AdjustWindowRect(&size, WS_OVERLAPPEDWINDOW, false);
|
||||
const UINT flags = SWP_NOMOVE | SWP_NOZORDER | SWP_SHOWWINDOW;
|
||||
if (!SetWindowPos(Window, nullptr, 0, 0, size.right - size.left, size.bottom - size.top, flags))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetAndClearRenderTarget(ID3D11RenderTargetView *rendertarget, DepthBuffer *depthbuffer, float R = 0, float G = 0, float B = 0, float A = 0) {
|
||||
float black[] = {R, G, B, A}; // Important that alpha=0, if want pixels to be transparent, for manual layers
|
||||
dx_ctx.context->OMSetRenderTargets(1, &rendertarget, (depthbuffer ? depthbuffer->TexDsv : nullptr));
|
||||
dx_ctx.context->ClearRenderTargetView(rendertarget, black);
|
||||
if (depthbuffer)
|
||||
dx_ctx.context->ClearDepthStencilView(depthbuffer->TexDsv, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1, 0);
|
||||
}
|
||||
|
||||
void SetViewport(float vpX, float vpY, float vpW, float vpH) {
|
||||
D3D11_VIEWPORT D3Dvp;
|
||||
D3Dvp.Width = vpW;
|
||||
D3Dvp.Height = vpH;
|
||||
D3Dvp.MinDepth = 0;
|
||||
D3Dvp.MaxDepth = 1;
|
||||
D3Dvp.TopLeftX = vpX;
|
||||
D3Dvp.TopLeftY = vpY;
|
||||
dx_ctx.context->RSSetViewports(1, &D3Dvp);
|
||||
}
|
||||
|
||||
void ReleaseDevice() {}
|
||||
};
|
||||
|
||||
static DirectX11 Platform;
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
// ovrSwapTextureSet wrapper class that also maintains the render target views needed for D3D11 rendering.
|
||||
struct OculusTexture {
|
||||
ovrSession Session;
|
||||
ovrTextureSwapChain TextureChain;
|
||||
std::vector<ID3D11RenderTargetView *> TexRtv;
|
||||
|
||||
OculusTexture(ovrSession session, int sizeW, int sizeH, int sampleCount = 1) : Session(session), TextureChain(nullptr) {
|
||||
ovrTextureSwapChainDesc desc = {};
|
||||
desc.Type = ovrTexture_2D;
|
||||
desc.ArraySize = 1;
|
||||
desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
|
||||
desc.Width = sizeW;
|
||||
desc.Height = sizeH;
|
||||
desc.MipLevels = 1;
|
||||
desc.SampleCount = sampleCount;
|
||||
desc.MiscFlags = ovrTextureMisc_DX_Typeless | ovrTextureMisc_AutoGenerateMips;
|
||||
desc.BindFlags = ovrTextureBind_DX_RenderTarget;
|
||||
desc.StaticImage = ovrFalse;
|
||||
|
||||
ovrResult result = ovr_CreateTextureSwapChainDX(session, dx_ctx.device, &desc, &TextureChain);
|
||||
|
||||
int textureCount = 0;
|
||||
ovr_GetTextureSwapChainLength(Session, TextureChain, &textureCount);
|
||||
if (OVR_SUCCESS(result)) {
|
||||
for (int i = 0; i < textureCount; ++i) {
|
||||
ID3D11Texture2D *tex = nullptr;
|
||||
ovr_GetTextureSwapChainBufferDX(Session, TextureChain, i, IID_PPV_ARGS(&tex));
|
||||
D3D11_RENDER_TARGET_VIEW_DESC rtvd = {};
|
||||
rtvd.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
rtvd.ViewDimension = (sampleCount > 1) ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
|
||||
ID3D11RenderTargetView *rtv;
|
||||
dx_ctx.device->CreateRenderTargetView(tex, &rtvd, &rtv);
|
||||
TexRtv.push_back(rtv);
|
||||
tex->Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~OculusTexture() {
|
||||
for (int i = 0; i < (int)TexRtv.size(); ++i) {
|
||||
TexRtv[i]->Release();
|
||||
TexRtv[i] = nullptr;
|
||||
}
|
||||
if (TextureChain) {
|
||||
ovr_DestroyTextureSwapChain(Session, TextureChain);
|
||||
TextureChain = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ID3D11RenderTargetView *GetRTV() {
|
||||
int index = 0;
|
||||
ovr_GetTextureSwapChainCurrentIndex(Session, TextureChain, &index);
|
||||
return TexRtv[index];
|
||||
}
|
||||
|
||||
void Commit() {
|
||||
ovr_CommitTextureSwapChain(Session, TextureChain);
|
||||
}
|
||||
};
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
namespace {
|
||||
// Initialize these to nullptr here to handle dx_ctx.device lost failures cleanly
|
||||
ovrMirrorTexture mirrorTexture = nullptr;
|
||||
OculusTexture *pEyeRenderTexture[2] = {nullptr, nullptr};
|
||||
DepthBuffer *pEyeDepthBuffer[2] = {nullptr, nullptr};
|
||||
|
||||
ovrSizei windowSize;
|
||||
|
||||
long long frameIndex = 0;
|
||||
int msaaRate = 4;
|
||||
|
||||
bool isVisible = true;
|
||||
|
||||
ovrSession session;
|
||||
ovrHmdDesc hmdDesc;
|
||||
|
||||
ovrPosef EyeRenderPose[2];
|
||||
double sensorSampleTime;
|
||||
|
||||
// Make the eye render buffers (caution if actual size < requested due to HW limits).
|
||||
ovrRecti eyeRenderViewport[2];
|
||||
|
||||
void done() {
|
||||
if (mirrorTexture)
|
||||
ovr_DestroyMirrorTexture(session, mirrorTexture);
|
||||
for (int eye = 0; eye < 2; ++eye) {
|
||||
delete pEyeRenderTexture[eye];
|
||||
delete pEyeDepthBuffer[eye];
|
||||
}
|
||||
Platform.ReleaseDevice();
|
||||
ovr_Destroy(session);
|
||||
}
|
||||
|
||||
void createOculusTexture() {
|
||||
// Create mirror texture
|
||||
ovrMirrorTextureDesc mirrorDesc;
|
||||
memset(&mirrorDesc, 0, sizeof(mirrorDesc));
|
||||
mirrorDesc.Width = Platform.WinSizeW;
|
||||
mirrorDesc.Height = Platform.WinSizeH;
|
||||
mirrorDesc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
|
||||
mirrorDesc.MirrorOptions = ovrMirrorOption_Default;
|
||||
HRESULT result = ovr_CreateMirrorTextureWithOptionsDX(session, dx_ctx.device, &mirrorDesc, &mirrorTexture);
|
||||
if (!OVR_SUCCESS(result)) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Failed to create mirror texture.");
|
||||
done();
|
||||
}
|
||||
|
||||
// Make eye render buffers
|
||||
for (int eye = 0; eye < 2; ++eye) {
|
||||
ovrSizei idealSize = ovr_GetFovTextureSize(session, ovrEyeType(eye), hmdDesc.DefaultEyeFov[eye], 1);
|
||||
pEyeRenderTexture[eye] = new OculusTexture(session, idealSize.w, idealSize.h);
|
||||
pEyeDepthBuffer[eye] = new DepthBuffer(dx_ctx.device, idealSize.w, idealSize.h);
|
||||
eyeRenderViewport[eye].Pos.x = 0;
|
||||
eyeRenderViewport[eye].Pos.y = 0;
|
||||
eyeRenderViewport[eye].Size = idealSize;
|
||||
if (!pEyeRenderTexture[eye]->TextureChain) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Failed to create texture.");
|
||||
done();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void *kinc_vr_interface_init(void *hinst, const char *title, const char *windowClassName) {
|
||||
// Initializes LibOVR, and the Rift
|
||||
ovrInitParams initParams = {ovrInit_RequestVersion | ovrInit_FocusAware, OVR_MINOR_VERSION, NULL, 0, 0};
|
||||
ovrResult result = ovr_Initialize(&initParams);
|
||||
if (!OVR_SUCCESS(result)) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Failed to initialize libOVR.");
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (!Platform.InitWindow((HINSTANCE)hinst, title, windowClassName)) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Failed to open window.");
|
||||
return (0);
|
||||
}
|
||||
|
||||
ovrGraphicsLuid luid;
|
||||
result = ovr_Create(&session, &luid);
|
||||
if (!OVR_SUCCESS(result)) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "HMD not connected.");
|
||||
return false; // TODO: retry
|
||||
}
|
||||
|
||||
hmdDesc = ovr_GetHmdDesc(session);
|
||||
|
||||
// Setup Window and Graphics
|
||||
// Note: the mirror window can be any size, for this sample we use 1/2 the HMD resolution
|
||||
windowSize = {hmdDesc.Resolution.w / 2, hmdDesc.Resolution.h / 2};
|
||||
if (!Platform.InitDevice(windowSize.w, windowSize.h, reinterpret_cast<LUID *>(&luid))) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Failed to init dx_ctx.device.");
|
||||
done();
|
||||
}
|
||||
|
||||
// FloorLevel will give tracking poses where the floor height is 0
|
||||
ovr_SetTrackingOriginType(session, ovrTrackingOrigin_FloorLevel);
|
||||
|
||||
// Return window
|
||||
return Platform.Window;
|
||||
}
|
||||
|
||||
void kinc_vr_interface_begin() {
|
||||
// Call ovr_GetRenderDesc each frame to get the ovrEyeRenderDesc, as the returned values (e.g. HmdToEyeOffset) may change at runtime.
|
||||
ovrEyeRenderDesc eyeRenderDesc[2];
|
||||
eyeRenderDesc[0] = ovr_GetRenderDesc(session, ovrEye_Left, hmdDesc.DefaultEyeFov[0]);
|
||||
eyeRenderDesc[1] = ovr_GetRenderDesc(session, ovrEye_Right, hmdDesc.DefaultEyeFov[1]);
|
||||
|
||||
// Get both eye poses simultaneously, with IPD offset already included.
|
||||
ovrPosef HmdToEyePose[2] = {eyeRenderDesc[0].HmdToEyePose, eyeRenderDesc[1].HmdToEyePose};
|
||||
|
||||
ovr_GetEyePoses(session, frameIndex, ovrTrue, HmdToEyePose, EyeRenderPose, &sensorSampleTime);
|
||||
}
|
||||
|
||||
void kinc_vr_interface_begin_render(int eye) {
|
||||
if (pEyeRenderTexture[0] == nullptr || pEyeRenderTexture[1] == nullptr)
|
||||
createOculusTexture();
|
||||
|
||||
// Clear and set up rendertarget
|
||||
Platform.SetAndClearRenderTarget(pEyeRenderTexture[eye]->GetRTV(), pEyeDepthBuffer[eye]);
|
||||
Platform.SetViewport((float)eyeRenderViewport[eye].Pos.x, (float)eyeRenderViewport[eye].Pos.y, (float)eyeRenderViewport[eye].Size.w,
|
||||
(float)eyeRenderViewport[eye].Size.h);
|
||||
}
|
||||
|
||||
void kinc_vr_interface_end_render(int eye) {
|
||||
// Commit rendering to the swap chain
|
||||
pEyeRenderTexture[eye]->Commit();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
kinc_matrix4x4_t convert(XMMATRIX &m) {
|
||||
XMFLOAT4X4 fView;
|
||||
XMStoreFloat4x4(&fView, m);
|
||||
|
||||
kinc_matrix4x4_t mat;
|
||||
kinc_matrix4x4_set(&mat, 0, 0, fView._11);
|
||||
kinc_matrix4x4_set(&mat, 0, 1, fView._12);
|
||||
kinc_matrix4x4_set(&mat, 0, 2, fView._13);
|
||||
kinc_matrix4x4_set(&mat, 0, 3, fView._14);
|
||||
kinc_matrix4x4_set(&mat, 1, 0, fView._21);
|
||||
kinc_matrix4x4_set(&mat, 1, 1, fView._22);
|
||||
kinc_matrix4x4_set(&mat, 1, 2, fView._23);
|
||||
kinc_matrix4x4_set(&mat, 1, 3, fView._24);
|
||||
kinc_matrix4x4_set(&mat, 2, 0, fView._31);
|
||||
kinc_matrix4x4_set(&mat, 2, 1, fView._32);
|
||||
kinc_matrix4x4_set(&mat, 2, 2, fView._33);
|
||||
kinc_matrix4x4_set(&mat, 2, 3, fView._34);
|
||||
kinc_matrix4x4_set(&mat, 3, 0, fView._41);
|
||||
kinc_matrix4x4_set(&mat, 3, 1, fView._42);
|
||||
kinc_matrix4x4_set(&mat, 3, 2, fView._43);
|
||||
kinc_matrix4x4_set(&mat, 3, 3, fView._44);
|
||||
return mat;
|
||||
}
|
||||
}
|
||||
|
||||
kinc_vr_sensor_state_t kinc_vr_interface_get_sensor_state(int eye) {
|
||||
kinc_vr_pose_state_t poseState;
|
||||
|
||||
ovrQuatf orientation = EyeRenderPose[eye].Orientation;
|
||||
poseState.vrPose.orientation.x = orientation.x;
|
||||
poseState.vrPose.orientation.y = orientation.y;
|
||||
poseState.vrPose.orientation.z = orientation.z;
|
||||
poseState.vrPose.orientation.w = orientation.w;
|
||||
|
||||
ovrVector3f pos = EyeRenderPose[eye].Position;
|
||||
poseState.vrPose.position.x = pos.x;
|
||||
poseState.vrPose.position.y = pos.y;
|
||||
poseState.vrPose.position.z = pos.z;
|
||||
|
||||
ovrFovPort fov = hmdDesc.DefaultEyeFov[eye];
|
||||
poseState.vrPose.left = fov.LeftTan;
|
||||
poseState.vrPose.right = fov.RightTan;
|
||||
poseState.vrPose.bottom = fov.DownTan;
|
||||
poseState.vrPose.top = fov.UpTan;
|
||||
|
||||
// Get the pose information in XM format
|
||||
XMVECTOR eyeQuat = XMVectorSet(orientation.x, orientation.y, orientation.z, orientation.w);
|
||||
XMVECTOR eyePos = XMVectorSet(pos.x, pos.y, pos.z, 0);
|
||||
|
||||
// Get view and projection matrices for the Rift camera
|
||||
Camera finalCam(eyePos, eyeQuat);
|
||||
XMMATRIX view = finalCam.GetViewMatrix();
|
||||
ovrMatrix4f p = ovrMatrix4f_Projection(fov, 0.2f, 1000.0f, ovrProjection_None);
|
||||
XMMATRIX proj = XMMatrixSet(p.M[0][0], p.M[1][0], p.M[2][0], p.M[3][0], p.M[0][1], p.M[1][1], p.M[2][1], p.M[3][1], p.M[0][2], p.M[1][2], p.M[2][2],
|
||||
p.M[3][2], p.M[0][3], p.M[1][3], p.M[2][3], p.M[3][3]);
|
||||
|
||||
poseState.vrPose.eye = convert(view);
|
||||
kinc_matrix4x4_transpose(&poseState.vrPose.eye);
|
||||
poseState.vrPose.projection = convert(proj);
|
||||
kinc_matrix4x4_transpose(&poseState.vrPose.projection);
|
||||
|
||||
ovrSessionStatus sessionStatus;
|
||||
ovr_GetSessionStatus(session, &sessionStatus);
|
||||
poseState.isVisible = sessionStatus.IsVisible;
|
||||
poseState.hmdPresenting = sessionStatus.HmdPresent;
|
||||
poseState.hmdMounted = sessionStatus.HmdMounted;
|
||||
poseState.displayLost = sessionStatus.DisplayLost;
|
||||
poseState.shouldQuit = sessionStatus.ShouldQuit;
|
||||
poseState.shouldRecenter = sessionStatus.ShouldRecenter;
|
||||
|
||||
sensorStates[eye].pose = poseState;
|
||||
|
||||
return sensorStates[eye];
|
||||
}
|
||||
|
||||
kinc_vr_pose_state_t kinc_vr_interface_get_controller(int index) {
|
||||
kinc_vr_pose_state_t todo;
|
||||
return todo;
|
||||
}
|
||||
|
||||
void kinc_vr_interface_warp_swap() {
|
||||
// Initialize our single full screen Fov layer.
|
||||
ovrLayerEyeFov ld = {};
|
||||
ld.Header.Type = ovrLayerType_EyeFov;
|
||||
ld.Header.Flags = 0;
|
||||
|
||||
if (isVisible) {
|
||||
for (int eye = 0; eye < 2; ++eye) {
|
||||
ld.ColorTexture[eye] = pEyeRenderTexture[eye]->TextureChain;
|
||||
ld.Viewport[eye] = eyeRenderViewport[eye];
|
||||
ld.Fov[eye] = hmdDesc.DefaultEyeFov[eye];
|
||||
ld.RenderPose[eye] = EyeRenderPose[eye];
|
||||
ld.SensorSampleTime = sensorSampleTime;
|
||||
}
|
||||
}
|
||||
|
||||
ovrLayerHeader *layers = &ld.Header;
|
||||
ovrResult result = ovr_SubmitFrame(session, frameIndex, nullptr, &layers, 1);
|
||||
if (!OVR_SUCCESS(result)) {
|
||||
isVisible = false;
|
||||
}
|
||||
else {
|
||||
isVisible = true;
|
||||
}
|
||||
|
||||
frameIndex++;
|
||||
|
||||
// Render mirror
|
||||
ID3D11Texture2D *tex = nullptr;
|
||||
ovr_GetMirrorTextureBufferDX(session, mirrorTexture, IID_PPV_ARGS(&tex));
|
||||
|
||||
dx_ctx.context->CopyResource(backBuffer, tex);
|
||||
tex->Release();
|
||||
}
|
||||
|
||||
void kinc_vr_interface_update_tracking_origin(kinc_tracking_origin_t origin) {
|
||||
switch (origin) {
|
||||
case KINC_TRACKING_ORIGIN_STAND:
|
||||
ovr_SetTrackingOriginType(session, ovrTrackingOrigin_FloorLevel);
|
||||
break;
|
||||
case KINC_TRACKING_ORIGIN_SIT:
|
||||
ovr_SetTrackingOriginType(session, ovrTrackingOrigin_EyeLevel);
|
||||
break;
|
||||
default:
|
||||
ovr_SetTrackingOriginType(session, ovrTrackingOrigin_FloorLevel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_vr_interface_reset_hmd_pose() {
|
||||
ovr_RecenterTrackingOrigin(session);
|
||||
}
|
||||
|
||||
void kinc_vr_interface_ovr_shutdown() {
|
||||
ovr_Shutdown();
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,384 @@
|
||||
#include "graphics4/Direct3D11.h"
|
||||
|
||||
#include <kinc/graphics4/compute.h>
|
||||
#include <kinc/graphics4/texture.h>
|
||||
#include <kinc/log.h>
|
||||
#include <kinc/math/core.h>
|
||||
|
||||
#include <kinc/backend/SystemMicrosoft.h>
|
||||
|
||||
#define NOMINMAX
|
||||
|
||||
#ifdef KORE_WINDOWSAPP
|
||||
#include <d3d11_1.h>
|
||||
#else
|
||||
#pragma warning(disable : 4005)
|
||||
#include <d3d11.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
static uint8_t constantsMemory[1024 * 4];
|
||||
|
||||
static int getMultipleOf16(int value) {
|
||||
int ret = 16;
|
||||
while (ret < value)
|
||||
ret += 16;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void setInt(uint8_t *constants, uint32_t offset, uint32_t size, int value) {
|
||||
if (size == 0)
|
||||
return;
|
||||
int *ints = (int *)&constants[offset];
|
||||
ints[0] = value;
|
||||
}
|
||||
|
||||
static void setFloat(uint8_t *constants, uint32_t offset, uint32_t size, float value) {
|
||||
if (size == 0)
|
||||
return;
|
||||
float *floats = (float *)&constants[offset];
|
||||
floats[0] = value;
|
||||
}
|
||||
|
||||
static void setFloat2(uint8_t *constants, uint32_t offset, uint32_t size, float value1, float value2) {
|
||||
if (size == 0)
|
||||
return;
|
||||
float *floats = (float *)&constants[offset];
|
||||
floats[0] = value1;
|
||||
floats[1] = value2;
|
||||
}
|
||||
|
||||
static void setFloat3(uint8_t *constants, uint32_t offset, uint32_t size, float value1, float value2, float value3) {
|
||||
if (size == 0)
|
||||
return;
|
||||
float *floats = (float *)&constants[offset];
|
||||
floats[0] = value1;
|
||||
floats[1] = value2;
|
||||
floats[2] = value3;
|
||||
}
|
||||
|
||||
static void setFloat4(uint8_t *constants, uint32_t offset, uint32_t size, float value1, float value2, float value3, float value4) {
|
||||
if (size == 0)
|
||||
return;
|
||||
float *floats = (float *)&constants[offset];
|
||||
floats[0] = value1;
|
||||
floats[1] = value2;
|
||||
floats[2] = value3;
|
||||
floats[3] = value4;
|
||||
}
|
||||
|
||||
static void setFloats(uint8_t *constants, uint32_t offset, uint32_t size, uint8_t columns, uint8_t rows, float *values, int count) {
|
||||
if (size == 0)
|
||||
return;
|
||||
float *floats = (float *)&constants[offset];
|
||||
if (columns == 4 && rows == 4) {
|
||||
for (int i = 0; i < count / 16 && i < (int)size / 4; ++i) {
|
||||
for (int y = 0; y < 4; ++y) {
|
||||
for (int x = 0; x < 4; ++x) {
|
||||
floats[i * 16 + x + y * 4] = values[i * 16 + y + x * 4];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (columns == 3 && rows == 3) {
|
||||
for (int i = 0; i < count / 9 && i < (int)size / 3; ++i) {
|
||||
for (int y = 0; y < 4; ++y) {
|
||||
for (int x = 0; x < 4; ++x) {
|
||||
floats[i * 12 + x + y * 4] = values[i * 9 + y + x * 3];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (columns == 2 && rows == 2) {
|
||||
for (int i = 0; i < count / 4 && i < (int)size / 2; ++i) {
|
||||
for (int y = 0; y < 4; ++y) {
|
||||
for (int x = 0; x < 4; ++x) {
|
||||
floats[i * 8 + x + y * 4] = values[i * 4 + y + x * 2];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < count && i * 4 < (int)size; ++i) {
|
||||
floats[i] = values[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void setBool(uint8_t *constants, uint32_t offset, uint32_t size, bool value) {
|
||||
if (size == 0)
|
||||
return;
|
||||
int *ints = (int *)&constants[offset];
|
||||
ints[0] = value ? 1 : 0;
|
||||
}
|
||||
|
||||
static void setMatrix4(uint8_t *constants, uint32_t offset, uint32_t size, kinc_matrix4x4_t *value) {
|
||||
if (size == 0)
|
||||
return;
|
||||
float *floats = (float *)&constants[offset];
|
||||
for (int y = 0; y < 4; ++y) {
|
||||
for (int x = 0; x < 4; ++x) {
|
||||
floats[x + y * 4] = kinc_matrix4x4_get(value, y, x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void setMatrix3(uint8_t *constants, uint32_t offset, uint32_t size, kinc_matrix3x3_t *value) {
|
||||
if (size == 0)
|
||||
return;
|
||||
float *floats = (float *)&constants[offset];
|
||||
for (int y = 0; y < 3; ++y) {
|
||||
for (int x = 0; x < 3; ++x) {
|
||||
floats[x + y * 4] = kinc_matrix3x3_get(value, y, x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_compute_shader_init(kinc_compute_shader_t *shader, void *_data, int length) {
|
||||
unsigned index = 0;
|
||||
uint8_t *data = (uint8_t *)_data;
|
||||
|
||||
#ifndef KINC_KONG
|
||||
memset(&shader->impl.attributes, 0, sizeof(shader->impl.attributes));
|
||||
int attributesCount = data[index++];
|
||||
for (int i = 0; i < attributesCount; ++i) {
|
||||
unsigned char name[256];
|
||||
for (unsigned i2 = 0; i2 < 255; ++i2) {
|
||||
name[i2] = data[index++];
|
||||
if (name[i2] == 0)
|
||||
break;
|
||||
}
|
||||
shader->impl.attributes[i].hash = kinc_internal_hash_name(name);
|
||||
shader->impl.attributes[i].index = data[index++];
|
||||
}
|
||||
|
||||
memset(&shader->impl.textures, 0, sizeof(shader->impl.textures));
|
||||
uint8_t texCount = data[index++];
|
||||
for (unsigned i = 0; i < texCount; ++i) {
|
||||
unsigned char name[256];
|
||||
for (unsigned i2 = 0; i2 < 255; ++i2) {
|
||||
name[i2] = data[index++];
|
||||
if (name[i2] == 0)
|
||||
break;
|
||||
}
|
||||
shader->impl.textures[i].hash = kinc_internal_hash_name(name);
|
||||
shader->impl.textures[i].index = data[index++];
|
||||
}
|
||||
|
||||
memset(&shader->impl.constants, 0, sizeof(shader->impl.constants));
|
||||
uint8_t constantCount = data[index++];
|
||||
shader->impl.constantsSize = 0;
|
||||
for (unsigned i = 0; i < constantCount; ++i) {
|
||||
unsigned char name[256];
|
||||
for (unsigned i2 = 0; i2 < 255; ++i2) {
|
||||
name[i2] = data[index++];
|
||||
if (name[i2] == 0)
|
||||
break;
|
||||
}
|
||||
kinc_compute_internal_shader_constant_t constant;
|
||||
constant.hash = kinc_internal_hash_name(name);
|
||||
constant.offset = *(uint32_t *)&data[index];
|
||||
index += 4;
|
||||
constant.size = *(uint32_t *)&data[index];
|
||||
index += 4;
|
||||
constant.columns = data[index];
|
||||
index += 1;
|
||||
constant.rows = data[index];
|
||||
index += 1;
|
||||
|
||||
shader->impl.constants[i] = constant;
|
||||
shader->impl.constantsSize = constant.offset + constant.size;
|
||||
}
|
||||
#endif
|
||||
|
||||
shader->impl.length = (int)(length - index);
|
||||
shader->impl.data = (uint8_t *)malloc(shader->impl.length);
|
||||
assert(shader->impl.data != NULL);
|
||||
memcpy(shader->impl.data, &data[index], shader->impl.length);
|
||||
|
||||
HRESULT hr =
|
||||
dx_ctx.device->lpVtbl->CreateComputeShader(dx_ctx.device, shader->impl.data, shader->impl.length, NULL, (ID3D11ComputeShader **)&shader->impl.shader);
|
||||
|
||||
if (hr != S_OK) {
|
||||
kinc_log(KINC_LOG_LEVEL_WARNING, "Could not initialize compute shader.");
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef KINC_KONG
|
||||
D3D11_BUFFER_DESC desc;
|
||||
desc.ByteWidth = getMultipleOf16(shader->impl.constantsSize);
|
||||
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.CPUAccessFlags = 0;
|
||||
desc.MiscFlags = 0;
|
||||
desc.StructureByteStride = 0;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateBuffer(dx_ctx.device, &desc, NULL, &shader->impl.constantBuffer));
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_compute_shader_destroy(kinc_compute_shader_t *shader) {}
|
||||
|
||||
static kinc_compute_internal_shader_constant_t *findConstant(kinc_compute_internal_shader_constant_t *constants, uint32_t hash) {
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
if (constants[i].hash == hash) {
|
||||
return &constants[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static kinc_internal_hash_index_t *findTextureUnit(kinc_internal_hash_index_t *units, uint32_t hash) {
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
if (units[i].hash == hash) {
|
||||
return &units[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef KINC_KONG
|
||||
kinc_compute_constant_location_t kinc_compute_shader_get_constant_location(kinc_compute_shader_t *shader, const char *name) {
|
||||
kinc_compute_constant_location_t location;
|
||||
|
||||
uint32_t hash = kinc_internal_hash_name((unsigned char *)name);
|
||||
|
||||
kinc_compute_internal_shader_constant_t *constant = findConstant(shader->impl.constants, hash);
|
||||
if (constant == NULL) {
|
||||
location.impl.offset = 0;
|
||||
location.impl.size = 0;
|
||||
location.impl.columns = 0;
|
||||
location.impl.rows = 0;
|
||||
}
|
||||
else {
|
||||
location.impl.offset = constant->offset;
|
||||
location.impl.size = constant->size;
|
||||
location.impl.columns = constant->columns;
|
||||
location.impl.rows = constant->rows;
|
||||
}
|
||||
|
||||
if (location.impl.size == 0) {
|
||||
kinc_log(KINC_LOG_LEVEL_WARNING, "Uniform %s not found.", name);
|
||||
}
|
||||
|
||||
return location;
|
||||
}
|
||||
|
||||
kinc_compute_texture_unit_t kinc_compute_shader_get_texture_unit(kinc_compute_shader_t *shader, const char *name) {
|
||||
char unitName[64];
|
||||
int unitOffset = 0;
|
||||
size_t len = strlen(name);
|
||||
if (len > 63)
|
||||
len = 63;
|
||||
strncpy(unitName, name, len + 1);
|
||||
if (unitName[len - 1] == ']') { // Check for array - mySampler[2]
|
||||
unitOffset = (int)(unitName[len - 2] - '0'); // Array index is unit offset
|
||||
unitName[len - 3] = 0; // Strip array from name
|
||||
}
|
||||
|
||||
uint32_t hash = kinc_internal_hash_name((unsigned char *)unitName);
|
||||
|
||||
kinc_compute_texture_unit_t unit;
|
||||
kinc_internal_hash_index_t *vertexUnit = findTextureUnit(shader->impl.textures, hash);
|
||||
if (vertexUnit == NULL) {
|
||||
unit.impl.unit = -1;
|
||||
#ifndef NDEBUG
|
||||
static int notFoundCount = 0;
|
||||
if (notFoundCount < 10) {
|
||||
kinc_log(KINC_LOG_LEVEL_WARNING, "Sampler %s not found.", unitName);
|
||||
++notFoundCount;
|
||||
}
|
||||
else if (notFoundCount == 10) {
|
||||
kinc_log(KINC_LOG_LEVEL_WARNING, "Giving up on sampler not found messages.", unitName);
|
||||
++notFoundCount;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
unit.impl.unit = vertexUnit->index + unitOffset;
|
||||
}
|
||||
return unit;
|
||||
}
|
||||
#endif
|
||||
|
||||
void kinc_compute_set_bool(kinc_compute_constant_location_t location, bool value) {
|
||||
setBool(constantsMemory, location.impl.offset, location.impl.size, value);
|
||||
}
|
||||
|
||||
void kinc_compute_set_int(kinc_compute_constant_location_t location, int value) {
|
||||
setInt(constantsMemory, location.impl.offset, location.impl.size, value);
|
||||
}
|
||||
|
||||
void kinc_compute_set_float(kinc_compute_constant_location_t location, float value) {
|
||||
setFloat(constantsMemory, location.impl.offset, location.impl.size, value);
|
||||
}
|
||||
|
||||
void kinc_compute_set_float2(kinc_compute_constant_location_t location, float value1, float value2) {
|
||||
setFloat2(constantsMemory, location.impl.offset, location.impl.size, value1, value2);
|
||||
}
|
||||
|
||||
void kinc_compute_set_float3(kinc_compute_constant_location_t location, float value1, float value2, float value3) {
|
||||
setFloat3(constantsMemory, location.impl.offset, location.impl.size, value1, value2, value3);
|
||||
}
|
||||
|
||||
void kinc_compute_set_float4(kinc_compute_constant_location_t location, float value1, float value2, float value3, float value4) {
|
||||
setFloat4(constantsMemory, location.impl.offset, location.impl.size, value1, value2, value3, value4);
|
||||
}
|
||||
|
||||
void kinc_compute_set_floats(kinc_compute_constant_location_t location, float *values, int count) {
|
||||
setFloats(constantsMemory, location.impl.offset, location.impl.size, location.impl.columns, location.impl.rows, values, count);
|
||||
}
|
||||
|
||||
void kinc_compute_set_matrix4(kinc_compute_constant_location_t location, kinc_matrix4x4_t *value) {
|
||||
setMatrix4(constantsMemory, location.impl.offset, location.impl.size, value);
|
||||
}
|
||||
|
||||
void kinc_compute_set_matrix3(kinc_compute_constant_location_t location, kinc_matrix3x3_t *value) {
|
||||
setMatrix3(constantsMemory, location.impl.offset, location.impl.size, value);
|
||||
}
|
||||
|
||||
void kinc_compute_set_texture(kinc_compute_texture_unit_t unit, struct kinc_g4_texture *texture, kinc_compute_access_t access) {
|
||||
ID3D11ShaderResourceView *nullView = NULL;
|
||||
dx_ctx.context->lpVtbl->PSSetShaderResources(dx_ctx.context, 0, 1, &nullView);
|
||||
|
||||
dx_ctx.context->lpVtbl->CSSetUnorderedAccessViews(dx_ctx.context, unit.impl.unit, 1, &texture->impl.computeView, NULL);
|
||||
}
|
||||
|
||||
void kinc_compute_set_render_target(kinc_compute_texture_unit_t unit, struct kinc_g4_render_target *texture, kinc_compute_access_t access) {}
|
||||
|
||||
void kinc_compute_set_sampled_texture(kinc_compute_texture_unit_t unit, struct kinc_g4_texture *texture) {}
|
||||
|
||||
void kinc_compute_set_sampled_render_target(kinc_compute_texture_unit_t unit, struct kinc_g4_render_target *target) {}
|
||||
|
||||
void kinc_compute_set_sampled_depth_from_render_target(kinc_compute_texture_unit_t unit, struct kinc_g4_render_target *target) {}
|
||||
|
||||
void kinc_compute_set_texture_addressing(kinc_compute_texture_unit_t unit, kinc_g4_texture_direction_t dir, kinc_g4_texture_addressing_t addressing) {}
|
||||
|
||||
void kinc_compute_set_texture_magnification_filter(kinc_compute_texture_unit_t unit, kinc_g4_texture_filter_t filter) {}
|
||||
|
||||
void kinc_compute_set_texture_minification_filter(kinc_compute_texture_unit_t unit, kinc_g4_texture_filter_t filter) {}
|
||||
|
||||
void kinc_compute_set_texture_mipmap_filter(kinc_compute_texture_unit_t unit, kinc_g4_mipmap_filter_t filter) {}
|
||||
|
||||
void kinc_compute_set_texture3d_addressing(kinc_compute_texture_unit_t unit, kinc_g4_texture_direction_t dir, kinc_g4_texture_addressing_t addressing) {}
|
||||
|
||||
void kinc_compute_set_texture3d_magnification_filter(kinc_compute_texture_unit_t unit, kinc_g4_texture_filter_t filter) {}
|
||||
|
||||
void kinc_compute_set_texture3d_minification_filter(kinc_compute_texture_unit_t unit, kinc_g4_texture_filter_t filter) {}
|
||||
|
||||
void kinc_compute_set_texture3d_mipmap_filter(kinc_compute_texture_unit_t unit, kinc_g4_mipmap_filter_t filter) {}
|
||||
|
||||
void kinc_compute_set_shader(kinc_compute_shader_t *shader) {
|
||||
dx_ctx.context->lpVtbl->CSSetShader(dx_ctx.context, (ID3D11ComputeShader *)shader->impl.shader, NULL, 0);
|
||||
#ifndef KINC_KONG
|
||||
dx_ctx.context->lpVtbl->UpdateSubresource(dx_ctx.context, (ID3D11Resource *)shader->impl.constantBuffer, 0, NULL, constantsMemory, 0, 0);
|
||||
dx_ctx.context->lpVtbl->CSSetConstantBuffers(dx_ctx.context, 0, 1, &shader->impl.constantBuffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_compute(int x, int y, int z) {
|
||||
dx_ctx.context->lpVtbl->Dispatch(dx_ctx.context, x, y, z);
|
||||
|
||||
ID3D11UnorderedAccessView *nullView = NULL;
|
||||
dx_ctx.context->lpVtbl->CSSetUnorderedAccessViews(dx_ctx.context, 0, 1, &nullView, NULL);
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/backend/graphics4/ShaderHash.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ID3D11Buffer;
|
||||
|
||||
typedef struct {
|
||||
uint32_t offset;
|
||||
uint32_t size;
|
||||
uint8_t columns;
|
||||
uint8_t rows;
|
||||
} kinc_compute_constant_location_impl_t;
|
||||
|
||||
typedef struct {
|
||||
int unit;
|
||||
} kinc_compute_texture_unit_impl_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t hash;
|
||||
uint32_t offset;
|
||||
uint32_t size;
|
||||
uint8_t columns;
|
||||
uint8_t rows;
|
||||
} kinc_compute_internal_shader_constant_t;
|
||||
|
||||
typedef struct {
|
||||
#ifndef KINC_KONG
|
||||
kinc_compute_internal_shader_constant_t constants[64];
|
||||
int constantsSize;
|
||||
kinc_internal_hash_index_t attributes[64];
|
||||
kinc_internal_hash_index_t textures[64];
|
||||
struct ID3D11Buffer *constantBuffer;
|
||||
#endif
|
||||
void *shader;
|
||||
uint8_t *data;
|
||||
int length;
|
||||
} kinc_compute_shader_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include <d3d11.h>
|
||||
#include <dxgi.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define MAXIMUM_WINDOWS 16
|
||||
|
||||
struct dx_window {
|
||||
HWND hwnd;
|
||||
IDXGISwapChain *swapChain;
|
||||
ID3D11Texture2D *backBuffer;
|
||||
ID3D11RenderTargetView *renderTargetView;
|
||||
ID3D11Texture2D *depthStencil;
|
||||
ID3D11DepthStencilView *depthStencilView;
|
||||
|
||||
int width;
|
||||
int height;
|
||||
|
||||
int new_width;
|
||||
int new_height;
|
||||
|
||||
bool vsync;
|
||||
int depth_bits;
|
||||
int stencil_bits;
|
||||
};
|
||||
|
||||
struct dx_context {
|
||||
ID3D11Device *device;
|
||||
ID3D11DeviceContext *context;
|
||||
IDXGIDevice *dxgiDevice;
|
||||
IDXGIAdapter *dxgiAdapter;
|
||||
IDXGIFactory *dxgiFactory;
|
||||
|
||||
int current_window;
|
||||
struct dx_window windows[MAXIMUM_WINDOWS];
|
||||
};
|
||||
|
||||
extern struct dx_context dx_ctx;
|
||||
|
||||
#include <kinc/backend/SystemMicrosoft.h>
|
@ -0,0 +1,11 @@
|
||||
#include "ShaderHash.h"
|
||||
|
||||
// djb2
|
||||
uint32_t kinc_internal_hash_name(unsigned char *str) {
|
||||
unsigned long hash = 5381;
|
||||
int c;
|
||||
while (c = *str++) {
|
||||
hash = hash * 33 ^ c;
|
||||
}
|
||||
return hash;
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint32_t hash;
|
||||
uint32_t index;
|
||||
} kinc_internal_hash_index_t;
|
||||
|
||||
uint32_t kinc_internal_hash_name(unsigned char *str);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,51 @@
|
||||
#ifdef KINC_KONG
|
||||
|
||||
#include <kinc/graphics4/constantbuffer.h>
|
||||
|
||||
void kinc_g4_constant_buffer_init(kinc_g4_constant_buffer *buffer, size_t size) {
|
||||
buffer->impl.size = size;
|
||||
buffer->impl.last_start = 0;
|
||||
buffer->impl.last_size = size;
|
||||
|
||||
D3D11_BUFFER_DESC desc;
|
||||
desc.ByteWidth = (UINT)get_multiple_of_16(size);
|
||||
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
desc.MiscFlags = 0;
|
||||
desc.StructureByteStride = 0;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateBuffer(dx_ctx.device, &desc, NULL, &buffer->impl.buffer));
|
||||
}
|
||||
|
||||
void kinc_g4_constant_buffer_destroy(kinc_g4_constant_buffer *buffer) {
|
||||
buffer->impl.buffer->lpVtbl->Release(buffer->impl.buffer);
|
||||
}
|
||||
|
||||
uint8_t *kinc_g4_constant_buffer_lock_all(kinc_g4_constant_buffer *buffer) {
|
||||
return kinc_g4_constant_buffer_lock(buffer, 0, kinc_g4_constant_buffer_size(buffer));
|
||||
}
|
||||
|
||||
uint8_t *kinc_g4_constant_buffer_lock(kinc_g4_constant_buffer *buffer, size_t start, size_t size) {
|
||||
buffer->impl.last_start = start;
|
||||
buffer->impl.last_size = size;
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE mapped_resource;
|
||||
memset(&mapped_resource, 0, sizeof(D3D11_MAPPED_SUBRESOURCE));
|
||||
dx_ctx.context->lpVtbl->Map(dx_ctx.context, (ID3D11Resource *)buffer->impl.buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource);
|
||||
uint8_t *data = (uint8_t *)mapped_resource.pData;
|
||||
return &data[start];
|
||||
}
|
||||
|
||||
void kinc_g4_constant_buffer_unlock_all(kinc_g4_constant_buffer *buffer) {
|
||||
kinc_g4_constant_buffer_unlock(buffer, buffer->impl.last_size);
|
||||
}
|
||||
|
||||
void kinc_g4_constant_buffer_unlock(kinc_g4_constant_buffer *buffer, size_t count) {
|
||||
dx_ctx.context->lpVtbl->Unmap(dx_ctx.context, (ID3D11Resource *)buffer->impl.buffer, 0);
|
||||
}
|
||||
|
||||
size_t kinc_g4_constant_buffer_size(kinc_g4_constant_buffer *buffer) {
|
||||
return buffer->impl.size;
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef KINC_KONG
|
||||
|
||||
struct ID3D11Buffer;
|
||||
|
||||
typedef struct kinc_g4_constant_buffer_impl {
|
||||
struct ID3D11Buffer *buffer;
|
||||
size_t size;
|
||||
size_t last_start;
|
||||
size_t last_size;
|
||||
} kinc_g4_constant_buffer_impl;
|
||||
|
||||
#endif
|
@ -0,0 +1,108 @@
|
||||
// Windows 7
|
||||
#define WINVER 0x0601
|
||||
#define _WIN32_WINNT 0x0601
|
||||
|
||||
#define NOATOM
|
||||
#define NOCLIPBOARD
|
||||
#define NOCOLOR
|
||||
#define NOCOMM
|
||||
#define NOCTLMGR
|
||||
#define NODEFERWINDOWPOS
|
||||
#define NODRAWTEXT
|
||||
#define NOGDI
|
||||
#define NOGDICAPMASKS
|
||||
#define NOHELP
|
||||
#define NOICONS
|
||||
#define NOKANJI
|
||||
#define NOKEYSTATES
|
||||
#define NOMB
|
||||
#define NOMCX
|
||||
#define NOMEMMGR
|
||||
#define NOMENUS
|
||||
#define NOMETAFILE
|
||||
#define NOMINMAX
|
||||
//#define NOMSG
|
||||
#define NONLS
|
||||
#define NOOPENFILE
|
||||
#define NOPROFILER
|
||||
#define NORASTEROPS
|
||||
#define NOSCROLL
|
||||
#define NOSERVICE
|
||||
#define NOSHOWWINDOW
|
||||
#define NOSOUND
|
||||
#define NOSYSCOMMANDS
|
||||
#define NOSYSMETRICS
|
||||
#define NOTEXTMETRIC
|
||||
//#define NOUSER
|
||||
#define NOVIRTUALKEYCODES
|
||||
#define NOWH
|
||||
#define NOWINMESSAGES
|
||||
#define NOWINOFFSETS
|
||||
#define NOWINSTYLES
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
#include <kinc/graphics4/graphics.h>
|
||||
|
||||
#include <kinc/backend/SystemMicrosoft.h>
|
||||
|
||||
#ifdef KORE_WINDOWSAPP
|
||||
#include <d3d11_1.h>
|
||||
#else
|
||||
#pragma warning(disable : 4005)
|
||||
#include <d3d11.h>
|
||||
#endif
|
||||
|
||||
#include "Direct3D11.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <malloc.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct dx_context dx_ctx = {0};
|
||||
|
||||
static uint8_t vertexConstants[1024 * 4];
|
||||
static uint8_t fragmentConstants[1024 * 4];
|
||||
static uint8_t geometryConstants[1024 * 4];
|
||||
static uint8_t tessControlConstants[1024 * 4];
|
||||
static uint8_t tessEvalConstants[1024 * 4];
|
||||
|
||||
static D3D11_COMPARISON_FUNC get_comparison(kinc_g4_compare_mode_t compare) {
|
||||
switch (compare) {
|
||||
default:
|
||||
case KINC_G4_COMPARE_ALWAYS:
|
||||
return D3D11_COMPARISON_ALWAYS;
|
||||
case KINC_G4_COMPARE_NEVER:
|
||||
return D3D11_COMPARISON_NEVER;
|
||||
case KINC_G4_COMPARE_EQUAL:
|
||||
return D3D11_COMPARISON_EQUAL;
|
||||
case KINC_G4_COMPARE_NOT_EQUAL:
|
||||
return D3D11_COMPARISON_NOT_EQUAL;
|
||||
case KINC_G4_COMPARE_LESS:
|
||||
return D3D11_COMPARISON_LESS;
|
||||
case KINC_G4_COMPARE_LESS_EQUAL:
|
||||
return D3D11_COMPARISON_LESS_EQUAL;
|
||||
case KINC_G4_COMPARE_GREATER:
|
||||
return D3D11_COMPARISON_GREATER;
|
||||
case KINC_G4_COMPARE_GREATER_EQUAL:
|
||||
return D3D11_COMPARISON_GREATER_EQUAL;
|
||||
}
|
||||
}
|
||||
|
||||
static size_t get_multiple_of_16(size_t value) {
|
||||
size_t ret = 16;
|
||||
while (ret < value) {
|
||||
ret += 16;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#include "Direct3D11.c.h"
|
||||
#include "ShaderHash.c.h"
|
||||
#include "constantbuffer.c.h"
|
||||
#include "indexbuffer.c.h"
|
||||
#include "pipeline.c.h"
|
||||
#include "rendertarget.c.h"
|
||||
#include "shader.c.h"
|
||||
#include "texture.c.h"
|
||||
#include "texturearray.c.h"
|
||||
#include "vertexbuffer.c.h"
|
@ -0,0 +1,89 @@
|
||||
#include <kinc/graphics4/indexBuffer.h>
|
||||
|
||||
void kinc_g4_index_buffer_init(kinc_g4_index_buffer_t *buffer, int count, kinc_g4_index_buffer_format_t format, kinc_g4_usage_t usage) {
|
||||
buffer->impl.count = count;
|
||||
buffer->impl.sixteen = format == KINC_G4_INDEX_BUFFER_FORMAT_16BIT;
|
||||
buffer->impl.last_start = 0;
|
||||
buffer->impl.last_count = count;
|
||||
|
||||
uint32_t byte_size = buffer->impl.sixteen ? sizeof(uint16_t) * count : sizeof(uint32_t) * count;
|
||||
|
||||
if (usage == KINC_G4_USAGE_DYNAMIC) {
|
||||
buffer->impl.indices = NULL;
|
||||
}
|
||||
else {
|
||||
buffer->impl.indices = malloc(byte_size);
|
||||
}
|
||||
|
||||
D3D11_BUFFER_DESC bufferDesc;
|
||||
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
bufferDesc.ByteWidth = byte_size;
|
||||
bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
|
||||
bufferDesc.CPUAccessFlags = 0;
|
||||
bufferDesc.MiscFlags = 0;
|
||||
bufferDesc.StructureByteStride = 0;
|
||||
|
||||
buffer->impl.usage = usage;
|
||||
switch (usage) {
|
||||
case KINC_G4_USAGE_STATIC:
|
||||
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
break;
|
||||
case KINC_G4_USAGE_DYNAMIC:
|
||||
bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
break;
|
||||
case KINC_G4_USAGE_READABLE:
|
||||
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateBuffer(dx_ctx.device, &bufferDesc, NULL, &buffer->impl.ib));
|
||||
}
|
||||
|
||||
void kinc_g4_index_buffer_destroy(kinc_g4_index_buffer_t *buffer) {
|
||||
buffer->impl.ib->lpVtbl->Release(buffer->impl.ib);
|
||||
free(buffer->impl.indices);
|
||||
buffer->impl.indices = NULL;
|
||||
}
|
||||
|
||||
static int kinc_g4_internal_index_buffer_stride(kinc_g4_index_buffer_t *buffer) {
|
||||
return buffer->impl.sixteen ? 2 : 4;
|
||||
}
|
||||
|
||||
void *kinc_g4_index_buffer_lock_all(kinc_g4_index_buffer_t *buffer) {
|
||||
return kinc_g4_index_buffer_lock(buffer, 0, kinc_g4_index_buffer_count(buffer));
|
||||
}
|
||||
|
||||
void *kinc_g4_index_buffer_lock(kinc_g4_index_buffer_t *buffer, int start, int count) {
|
||||
buffer->impl.last_start = start;
|
||||
buffer->impl.last_count = count;
|
||||
|
||||
if (buffer->impl.usage == KINC_G4_USAGE_DYNAMIC) {
|
||||
D3D11_MAPPED_SUBRESOURCE mappedResource;
|
||||
memset(&mappedResource, 0, sizeof(D3D11_MAPPED_SUBRESOURCE));
|
||||
dx_ctx.context->lpVtbl->Map(dx_ctx.context, (ID3D11Resource *)buffer->impl.ib, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
|
||||
uint8_t *data = (uint8_t *)mappedResource.pData;
|
||||
return &data[start * kinc_g4_internal_index_buffer_stride(buffer)];
|
||||
}
|
||||
else {
|
||||
uint8_t *data = (uint8_t *)buffer->impl.indices;
|
||||
return &data[start * kinc_g4_internal_index_buffer_stride(buffer)];
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_index_buffer_unlock_all(kinc_g4_index_buffer_t *buffer) {
|
||||
kinc_g4_index_buffer_unlock(buffer, buffer->impl.last_count);
|
||||
}
|
||||
|
||||
void kinc_g4_index_buffer_unlock(kinc_g4_index_buffer_t *buffer, int count) {
|
||||
if (buffer->impl.usage == KINC_G4_USAGE_DYNAMIC) {
|
||||
dx_ctx.context->lpVtbl->Unmap(dx_ctx.context, (ID3D11Resource *)buffer->impl.ib, 0);
|
||||
}
|
||||
else {
|
||||
dx_ctx.context->lpVtbl->UpdateSubresource(dx_ctx.context, (ID3D11Resource *)buffer->impl.ib, 0, NULL, buffer->impl.indices, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
int kinc_g4_index_buffer_count(kinc_g4_index_buffer_t *buffer) {
|
||||
return buffer->impl.count;
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
struct ID3D11Buffer;
|
||||
|
||||
typedef struct {
|
||||
struct ID3D11Buffer *ib;
|
||||
void *indices;
|
||||
int count;
|
||||
int usage;
|
||||
bool sixteen;
|
||||
int last_start;
|
||||
int last_count;
|
||||
} kinc_g4_index_buffer_impl_t;
|
@ -0,0 +1,876 @@
|
||||
#include <kinc/graphics4/pipeline.h>
|
||||
#include <kinc/graphics4/shader.h>
|
||||
#include <kinc/graphics4/vertexbuffer.h>
|
||||
#include <kinc/libs/stb_sprintf.h>
|
||||
#include <kinc/log.h>
|
||||
|
||||
kinc_g4_pipeline_t *currentPipeline = NULL;
|
||||
float currentBlendFactor[4] = {0, 0, 0, 0};
|
||||
bool needPipelineRebind = true;
|
||||
|
||||
static D3D11_CULL_MODE convert_cull_mode(kinc_g4_cull_mode_t cullMode) {
|
||||
switch (cullMode) {
|
||||
case KINC_G4_CULL_CLOCKWISE:
|
||||
return D3D11_CULL_BACK;
|
||||
case KINC_G4_CULL_COUNTER_CLOCKWISE:
|
||||
return D3D11_CULL_FRONT;
|
||||
case KINC_G4_CULL_NOTHING:
|
||||
return D3D11_CULL_NONE;
|
||||
default:
|
||||
assert(false);
|
||||
return D3D11_CULL_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
static D3D11_BLEND convert_blend_factor(kinc_g4_blending_factor_t factor) {
|
||||
switch (factor) {
|
||||
case KINC_G4_BLEND_ONE:
|
||||
return D3D11_BLEND_ONE;
|
||||
case KINC_G4_BLEND_ZERO:
|
||||
return D3D11_BLEND_ZERO;
|
||||
case KINC_G4_BLEND_SOURCE_ALPHA:
|
||||
return D3D11_BLEND_SRC_ALPHA;
|
||||
case KINC_G4_BLEND_DEST_ALPHA:
|
||||
return D3D11_BLEND_DEST_ALPHA;
|
||||
case KINC_G4_BLEND_INV_SOURCE_ALPHA:
|
||||
return D3D11_BLEND_INV_SRC_ALPHA;
|
||||
case KINC_G4_BLEND_INV_DEST_ALPHA:
|
||||
return D3D11_BLEND_INV_DEST_ALPHA;
|
||||
case KINC_G4_BLEND_SOURCE_COLOR:
|
||||
return D3D11_BLEND_SRC_COLOR;
|
||||
case KINC_G4_BLEND_DEST_COLOR:
|
||||
return D3D11_BLEND_DEST_COLOR;
|
||||
case KINC_G4_BLEND_INV_SOURCE_COLOR:
|
||||
return D3D11_BLEND_INV_SRC_COLOR;
|
||||
case KINC_G4_BLEND_INV_DEST_COLOR:
|
||||
return D3D11_BLEND_INV_DEST_COLOR;
|
||||
default:
|
||||
assert(false);
|
||||
return D3D11_BLEND_SRC_ALPHA;
|
||||
}
|
||||
}
|
||||
|
||||
static D3D11_BLEND_OP convert_blend_operation(kinc_g4_blending_operation_t operation) {
|
||||
switch (operation) {
|
||||
case KINC_G4_BLENDOP_ADD:
|
||||
return D3D11_BLEND_OP_ADD;
|
||||
case KINC_G4_BLENDOP_SUBTRACT:
|
||||
return D3D11_BLEND_OP_SUBTRACT;
|
||||
case KINC_G4_BLENDOP_REVERSE_SUBTRACT:
|
||||
return D3D11_BLEND_OP_REV_SUBTRACT;
|
||||
case KINC_G4_BLENDOP_MIN:
|
||||
return D3D11_BLEND_OP_MIN;
|
||||
case KINC_G4_BLENDOP_MAX:
|
||||
return D3D11_BLEND_OP_MAX;
|
||||
default:
|
||||
assert(false);
|
||||
return D3D11_BLEND_OP_ADD;
|
||||
}
|
||||
}
|
||||
|
||||
static D3D11_STENCIL_OP get_stencil_action(kinc_g4_stencil_action_t action) {
|
||||
switch (action) {
|
||||
default:
|
||||
case KINC_G4_STENCIL_KEEP:
|
||||
return D3D11_STENCIL_OP_KEEP;
|
||||
case KINC_G4_STENCIL_ZERO:
|
||||
return D3D11_STENCIL_OP_ZERO;
|
||||
case KINC_G4_STENCIL_REPLACE:
|
||||
return D3D11_STENCIL_OP_REPLACE;
|
||||
case KINC_G4_STENCIL_INCREMENT:
|
||||
return D3D11_STENCIL_OP_INCR;
|
||||
case KINC_G4_STENCIL_INCREMENT_WRAP:
|
||||
return D3D11_STENCIL_OP_INCR_SAT;
|
||||
case KINC_G4_STENCIL_DECREMENT:
|
||||
return D3D11_STENCIL_OP_DECR;
|
||||
case KINC_G4_STENCIL_DECREMENT_WRAP:
|
||||
return D3D11_STENCIL_OP_DECR_SAT;
|
||||
case KINC_G4_STENCIL_INVERT:
|
||||
return D3D11_STENCIL_OP_INVERT;
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_internal_set_constants(void) {
|
||||
#ifndef KINC_KONG
|
||||
if (currentPipeline->vertex_shader->impl.constantsSize > 0) {
|
||||
dx_ctx.context->lpVtbl->UpdateSubresource(dx_ctx.context, (ID3D11Resource *)currentPipeline->impl.vertexConstantBuffer, 0, NULL, vertexConstants, 0, 0);
|
||||
dx_ctx.context->lpVtbl->VSSetConstantBuffers(dx_ctx.context, 0, 1, ¤tPipeline->impl.vertexConstantBuffer);
|
||||
}
|
||||
if (currentPipeline->fragment_shader->impl.constantsSize > 0) {
|
||||
dx_ctx.context->lpVtbl->UpdateSubresource(dx_ctx.context, (ID3D11Resource *)currentPipeline->impl.fragmentConstantBuffer, 0, NULL, fragmentConstants, 0,
|
||||
0);
|
||||
dx_ctx.context->lpVtbl->PSSetConstantBuffers(dx_ctx.context, 0, 1, ¤tPipeline->impl.fragmentConstantBuffer);
|
||||
}
|
||||
if (currentPipeline->geometry_shader != NULL && currentPipeline->geometry_shader->impl.constantsSize > 0) {
|
||||
dx_ctx.context->lpVtbl->UpdateSubresource(dx_ctx.context, (ID3D11Resource *)currentPipeline->impl.geometryConstantBuffer, 0, NULL, geometryConstants, 0,
|
||||
0);
|
||||
dx_ctx.context->lpVtbl->GSSetConstantBuffers(dx_ctx.context, 0, 1, ¤tPipeline->impl.geometryConstantBuffer);
|
||||
}
|
||||
if (currentPipeline->tessellation_control_shader != NULL && currentPipeline->tessellation_control_shader->impl.constantsSize > 0) {
|
||||
dx_ctx.context->lpVtbl->UpdateSubresource(dx_ctx.context, (ID3D11Resource *)currentPipeline->impl.tessControlConstantBuffer, 0, NULL,
|
||||
tessControlConstants, 0, 0);
|
||||
dx_ctx.context->lpVtbl->HSSetConstantBuffers(dx_ctx.context, 0, 1, ¤tPipeline->impl.tessControlConstantBuffer);
|
||||
}
|
||||
if (currentPipeline->tessellation_evaluation_shader != NULL && currentPipeline->tessellation_evaluation_shader->impl.constantsSize > 0) {
|
||||
dx_ctx.context->lpVtbl->UpdateSubresource(dx_ctx.context, (ID3D11Resource *)currentPipeline->impl.tessEvalConstantBuffer, 0, NULL, tessEvalConstants, 0,
|
||||
0);
|
||||
dx_ctx.context->lpVtbl->DSSetConstantBuffers(dx_ctx.context, 0, 1, ¤tPipeline->impl.tessEvalConstantBuffer);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_g4_pipeline_init(struct kinc_g4_pipeline *state) {
|
||||
memset(state, 0, sizeof(struct kinc_g4_pipeline));
|
||||
kinc_g4_internal_pipeline_set_defaults(state);
|
||||
state->impl.d3d11inputLayout = NULL;
|
||||
state->impl.fragmentConstantBuffer = NULL;
|
||||
state->impl.vertexConstantBuffer = NULL;
|
||||
state->impl.geometryConstantBuffer = NULL;
|
||||
state->impl.tessEvalConstantBuffer = NULL;
|
||||
state->impl.tessControlConstantBuffer = NULL;
|
||||
state->impl.depthStencilState = NULL;
|
||||
state->impl.rasterizerState = NULL;
|
||||
state->impl.rasterizerStateScissor = NULL;
|
||||
state->impl.blendState = NULL;
|
||||
}
|
||||
|
||||
void kinc_g4_pipeline_destroy(struct kinc_g4_pipeline *state) {
|
||||
if (state->impl.d3d11inputLayout != NULL) {
|
||||
state->impl.d3d11inputLayout->lpVtbl->Release(state->impl.d3d11inputLayout);
|
||||
state->impl.d3d11inputLayout = NULL;
|
||||
}
|
||||
if (state->impl.fragmentConstantBuffer != NULL) {
|
||||
state->impl.fragmentConstantBuffer->lpVtbl->Release(state->impl.fragmentConstantBuffer);
|
||||
state->impl.fragmentConstantBuffer = NULL;
|
||||
}
|
||||
if (state->impl.vertexConstantBuffer != NULL) {
|
||||
state->impl.vertexConstantBuffer->lpVtbl->Release(state->impl.vertexConstantBuffer);
|
||||
state->impl.vertexConstantBuffer = NULL;
|
||||
}
|
||||
if (state->impl.geometryConstantBuffer != NULL) {
|
||||
state->impl.geometryConstantBuffer->lpVtbl->Release(state->impl.geometryConstantBuffer);
|
||||
state->impl.geometryConstantBuffer = NULL;
|
||||
}
|
||||
if (state->impl.tessEvalConstantBuffer != NULL) {
|
||||
state->impl.tessEvalConstantBuffer->lpVtbl->Release(state->impl.tessEvalConstantBuffer);
|
||||
state->impl.tessEvalConstantBuffer = NULL;
|
||||
}
|
||||
if (state->impl.tessControlConstantBuffer != NULL) {
|
||||
state->impl.tessControlConstantBuffer->lpVtbl->Release(state->impl.tessControlConstantBuffer);
|
||||
state->impl.tessControlConstantBuffer = NULL;
|
||||
}
|
||||
if (state->impl.depthStencilState != NULL) {
|
||||
state->impl.depthStencilState->lpVtbl->Release(state->impl.depthStencilState);
|
||||
state->impl.depthStencilState = NULL;
|
||||
}
|
||||
if (state->impl.rasterizerState != NULL) {
|
||||
state->impl.rasterizerState->lpVtbl->Release(state->impl.rasterizerState);
|
||||
state->impl.rasterizerState = NULL;
|
||||
}
|
||||
if (state->impl.rasterizerStateScissor != NULL) {
|
||||
state->impl.rasterizerStateScissor->lpVtbl->Release(state->impl.rasterizerStateScissor);
|
||||
state->impl.rasterizerStateScissor = NULL;
|
||||
}
|
||||
if (state->impl.blendState != NULL) {
|
||||
state->impl.blendState->lpVtbl->Release(state->impl.blendState);
|
||||
state->impl.blendState = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_internal_set_rasterizer_state(struct kinc_g4_pipeline *pipeline, bool scissoring) {
|
||||
if (scissoring && pipeline->impl.rasterizerStateScissor != NULL)
|
||||
dx_ctx.context->lpVtbl->RSSetState(dx_ctx.context, pipeline->impl.rasterizerStateScissor);
|
||||
else if (pipeline->impl.rasterizerState != NULL)
|
||||
dx_ctx.context->lpVtbl->RSSetState(dx_ctx.context, pipeline->impl.rasterizerState);
|
||||
}
|
||||
|
||||
void kinc_internal_set_pipeline(struct kinc_g4_pipeline *pipeline, bool scissoring) {
|
||||
dx_ctx.context->lpVtbl->OMSetDepthStencilState(dx_ctx.context, pipeline->impl.depthStencilState, pipeline->stencil_reference_value);
|
||||
UINT sampleMask = 0xffffffff;
|
||||
dx_ctx.context->lpVtbl->OMSetBlendState(dx_ctx.context, pipeline->impl.blendState, currentBlendFactor, sampleMask);
|
||||
kinc_internal_set_rasterizer_state(pipeline, scissoring);
|
||||
|
||||
dx_ctx.context->lpVtbl->VSSetShader(dx_ctx.context, (ID3D11VertexShader *)pipeline->vertex_shader->impl.shader, NULL, 0);
|
||||
dx_ctx.context->lpVtbl->PSSetShader(dx_ctx.context, (ID3D11PixelShader *)pipeline->fragment_shader->impl.shader, NULL, 0);
|
||||
|
||||
dx_ctx.context->lpVtbl->GSSetShader(dx_ctx.context,
|
||||
pipeline->geometry_shader != NULL ? (ID3D11GeometryShader *)pipeline->geometry_shader->impl.shader : NULL, NULL, 0);
|
||||
dx_ctx.context->lpVtbl->HSSetShader(
|
||||
dx_ctx.context, pipeline->tessellation_control_shader != NULL ? (ID3D11HullShader *)pipeline->tessellation_control_shader->impl.shader : NULL, NULL, 0);
|
||||
dx_ctx.context->lpVtbl->DSSetShader(
|
||||
dx_ctx.context, pipeline->tessellation_evaluation_shader != NULL ? (ID3D11DomainShader *)pipeline->tessellation_evaluation_shader->impl.shader : NULL,
|
||||
NULL, 0);
|
||||
|
||||
dx_ctx.context->lpVtbl->IASetInputLayout(dx_ctx.context, pipeline->impl.d3d11inputLayout);
|
||||
}
|
||||
|
||||
void kinc_internal_pipeline_rebind() {
|
||||
if (currentPipeline != NULL && needPipelineRebind) {
|
||||
kinc_internal_set_pipeline(currentPipeline, kinc_internal_scissoring);
|
||||
needPipelineRebind = false;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef KINC_KONG
|
||||
static kinc_internal_shader_constant_t *findConstant(kinc_internal_shader_constant_t *constants, uint32_t hash) {
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
if (constants[i].hash == hash) {
|
||||
return &constants[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static kinc_internal_hash_index_t *findTextureUnit(kinc_internal_hash_index_t *units, uint32_t hash) {
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
if (units[i].hash == hash) {
|
||||
return &units[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void kinc_g4_pipeline_get_constant_locations(kinc_g4_pipeline_t *state, kinc_g4_constant_location_t *vertex_locations,
|
||||
kinc_g4_constant_location_t *fragment_locations, int *vertex_sizes, int *fragment_sizes, int *max_vertex,
|
||||
int *max_fragment) {
|
||||
|
||||
// *max_vertex = state->vertex_shader->impl.constantsSize;
|
||||
// *max_fragment = state->fragment_shader->impl.constantsSize;
|
||||
// if (vertex_locations != null && fragment_locations != null) {
|
||||
// for (int i = 0; i < state->vertex_shader->impl.constantsSize; i++) {
|
||||
// kinc_internal_shader_constant_t *constant = state->vertex_shader->impl.constants[i];
|
||||
// vertex_location[i].impl.vertexOffset = constant->offset;
|
||||
// vertex_location[i].impl.vertexSize = constant->size;
|
||||
// vertex_location[i].impl.vertexColumns = constant->columns;
|
||||
// vertex_location[i].impl.vertexRows = constant->rows;
|
||||
// vertex_sizes[i] = constant->size;
|
||||
// }
|
||||
|
||||
// for (int i = 0; i < state->fragment_shader->impl.constantsSize; i++) {
|
||||
// kinc_internal_shader_constant_t *constant = state->fragment_shader->impl.constants[i];
|
||||
// fragment_location[i].impl.vertexOffset = constant->offset;
|
||||
// fragment_location[i].impl.vertexSize = constant->size;
|
||||
// fragment_location[i].impl.vertexColumns = constant->columns;
|
||||
// fragment_location[i].impl.vertexRows = constant->rows;
|
||||
// fragment_sizes[i] = constant->size;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
kinc_g4_constant_location_t kinc_g4_pipeline_get_constant_location(struct kinc_g4_pipeline *state, const char *name) {
|
||||
kinc_g4_constant_location_t location;
|
||||
|
||||
uint32_t hash = kinc_internal_hash_name((unsigned char *)name);
|
||||
|
||||
kinc_internal_shader_constant_t *constant = findConstant(state->vertex_shader->impl.constants, hash);
|
||||
if (constant == NULL) {
|
||||
location.impl.vertexOffset = 0;
|
||||
location.impl.vertexSize = 0;
|
||||
location.impl.vertexColumns = 0;
|
||||
location.impl.vertexRows = 0;
|
||||
}
|
||||
else {
|
||||
location.impl.vertexOffset = constant->offset;
|
||||
location.impl.vertexSize = constant->size;
|
||||
location.impl.vertexColumns = constant->columns;
|
||||
location.impl.vertexRows = constant->rows;
|
||||
}
|
||||
|
||||
constant = findConstant(state->fragment_shader->impl.constants, hash);
|
||||
if (constant == NULL) {
|
||||
location.impl.fragmentOffset = 0;
|
||||
location.impl.fragmentSize = 0;
|
||||
location.impl.fragmentColumns = 0;
|
||||
location.impl.fragmentRows = 0;
|
||||
}
|
||||
else {
|
||||
location.impl.fragmentOffset = constant->offset;
|
||||
location.impl.fragmentSize = constant->size;
|
||||
location.impl.fragmentColumns = constant->columns;
|
||||
location.impl.fragmentRows = constant->rows;
|
||||
}
|
||||
|
||||
constant = state->geometry_shader == NULL ? NULL : findConstant(state->geometry_shader->impl.constants, hash);
|
||||
if (constant == NULL) {
|
||||
location.impl.geometryOffset = 0;
|
||||
location.impl.geometrySize = 0;
|
||||
location.impl.geometryColumns = 0;
|
||||
location.impl.geometryRows = 0;
|
||||
}
|
||||
else {
|
||||
location.impl.geometryOffset = constant->offset;
|
||||
location.impl.geometrySize = constant->size;
|
||||
location.impl.geometryColumns = constant->columns;
|
||||
location.impl.geometryRows = constant->rows;
|
||||
}
|
||||
|
||||
constant = state->tessellation_control_shader == NULL ? NULL : findConstant(state->tessellation_control_shader->impl.constants, hash);
|
||||
if (constant == NULL) {
|
||||
location.impl.tessControlOffset = 0;
|
||||
location.impl.tessControlSize = 0;
|
||||
location.impl.tessControlColumns = 0;
|
||||
location.impl.tessControlRows = 0;
|
||||
}
|
||||
else {
|
||||
location.impl.tessControlOffset = constant->offset;
|
||||
location.impl.tessControlSize = constant->size;
|
||||
location.impl.tessControlColumns = constant->columns;
|
||||
location.impl.tessControlRows = constant->rows;
|
||||
}
|
||||
|
||||
constant = state->tessellation_evaluation_shader == NULL ? NULL : findConstant(state->tessellation_evaluation_shader->impl.constants, hash);
|
||||
if (constant == NULL) {
|
||||
location.impl.tessEvalOffset = 0;
|
||||
location.impl.tessEvalSize = 0;
|
||||
location.impl.tessEvalColumns = 0;
|
||||
location.impl.tessEvalRows = 0;
|
||||
}
|
||||
else {
|
||||
location.impl.tessEvalOffset = constant->offset;
|
||||
location.impl.tessEvalSize = constant->size;
|
||||
location.impl.tessEvalColumns = constant->columns;
|
||||
location.impl.tessEvalRows = constant->rows;
|
||||
}
|
||||
|
||||
if (location.impl.vertexSize == 0 && location.impl.fragmentSize == 0 && location.impl.geometrySize == 0 && location.impl.tessControlSize == 0 &&
|
||||
location.impl.tessEvalSize == 0) {
|
||||
kinc_log(KINC_LOG_LEVEL_WARNING, "Uniform %s not found.", name);
|
||||
}
|
||||
|
||||
return location;
|
||||
}
|
||||
|
||||
kinc_g4_texture_unit_t kinc_g4_pipeline_get_texture_unit(struct kinc_g4_pipeline *state, const char *name) {
|
||||
char unitName[64];
|
||||
int unitOffset = 0;
|
||||
size_t len = strlen(name);
|
||||
if (len > 63)
|
||||
len = 63;
|
||||
strncpy(unitName, name, len + 1);
|
||||
if (unitName[len - 1] == ']') { // Check for array - mySampler[2]
|
||||
unitOffset = (int)(unitName[len - 2] - '0'); // Array index is unit offset
|
||||
unitName[len - 3] = 0; // Strip array from name
|
||||
}
|
||||
|
||||
uint32_t hash = kinc_internal_hash_name((unsigned char *)unitName);
|
||||
|
||||
kinc_g4_texture_unit_t unit;
|
||||
for (int i = 0; i < KINC_G4_SHADER_TYPE_COUNT; ++i) {
|
||||
unit.stages[i] = -1;
|
||||
}
|
||||
|
||||
kinc_internal_hash_index_t *fragmentUnit = findTextureUnit(state->fragment_shader->impl.textures, hash);
|
||||
if (fragmentUnit != NULL) {
|
||||
unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] = fragmentUnit->index + unitOffset;
|
||||
}
|
||||
|
||||
kinc_internal_hash_index_t *vertexUnit = findTextureUnit(state->vertex_shader->impl.textures, hash);
|
||||
if (vertexUnit != NULL) {
|
||||
unit.stages[KINC_G4_SHADER_TYPE_VERTEX] = vertexUnit->index + unitOffset;
|
||||
}
|
||||
|
||||
return unit;
|
||||
}
|
||||
#endif
|
||||
|
||||
static char stringCache[1024];
|
||||
static int stringCacheIndex = 0;
|
||||
|
||||
static void setVertexDesc(D3D11_INPUT_ELEMENT_DESC *vertexDesc, int attributeIndex, int index, int stream, bool instanced, int subindex) {
|
||||
if (subindex < 0) {
|
||||
vertexDesc->SemanticName = "TEXCOORD";
|
||||
vertexDesc->SemanticIndex = attributeIndex;
|
||||
}
|
||||
else {
|
||||
// SPIRV_CROSS uses TEXCOORD_0_0,... for split up matrices
|
||||
int stringStart = stringCacheIndex;
|
||||
strcpy(&stringCache[stringCacheIndex], "TEXCOORD");
|
||||
stringCacheIndex += (int)strlen("TEXCOORD");
|
||||
sprintf(&stringCache[stringCacheIndex], "%i", attributeIndex);
|
||||
stringCacheIndex += (int)strlen(&stringCache[stringCacheIndex]);
|
||||
strcpy(&stringCache[stringCacheIndex], "_");
|
||||
stringCacheIndex += 2;
|
||||
vertexDesc->SemanticName = &stringCache[stringStart];
|
||||
vertexDesc->SemanticIndex = subindex;
|
||||
}
|
||||
vertexDesc->InputSlot = stream;
|
||||
vertexDesc->AlignedByteOffset = (index == 0) ? 0 : D3D11_APPEND_ALIGNED_ELEMENT;
|
||||
vertexDesc->InputSlotClass = instanced ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA;
|
||||
vertexDesc->InstanceDataStepRate = instanced ? 1 : 0;
|
||||
}
|
||||
|
||||
#define usedCount 32
|
||||
|
||||
static int getAttributeLocation(kinc_internal_hash_index_t *attributes, const char *name, bool *used) {
|
||||
uint32_t hash = kinc_internal_hash_name((unsigned char *)name);
|
||||
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
if (attributes[i].hash == hash) {
|
||||
return attributes[i].index;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < usedCount; ++i) {
|
||||
if (!used[i]) {
|
||||
used[i] = true;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void createRenderTargetBlendDesc(struct kinc_g4_pipeline *pipe, D3D11_RENDER_TARGET_BLEND_DESC *rtbd, int targetNum) {
|
||||
rtbd->BlendEnable = pipe->blend_source != KINC_G4_BLEND_ONE || pipe->blend_destination != KINC_G4_BLEND_ZERO ||
|
||||
pipe->alpha_blend_source != KINC_G4_BLEND_ONE || pipe->alpha_blend_destination != KINC_G4_BLEND_ZERO;
|
||||
rtbd->SrcBlend = convert_blend_factor(pipe->blend_source);
|
||||
rtbd->DestBlend = convert_blend_factor(pipe->blend_destination);
|
||||
rtbd->BlendOp = convert_blend_operation(pipe->blend_operation);
|
||||
rtbd->SrcBlendAlpha = convert_blend_factor(pipe->alpha_blend_source);
|
||||
rtbd->DestBlendAlpha = convert_blend_factor(pipe->alpha_blend_destination);
|
||||
rtbd->BlendOpAlpha = convert_blend_operation(pipe->alpha_blend_operation);
|
||||
rtbd->RenderTargetWriteMask = (((pipe->color_write_mask_red[targetNum] ? D3D11_COLOR_WRITE_ENABLE_RED : 0) |
|
||||
(pipe->color_write_mask_green[targetNum] ? D3D11_COLOR_WRITE_ENABLE_GREEN : 0)) |
|
||||
(pipe->color_write_mask_blue[targetNum] ? D3D11_COLOR_WRITE_ENABLE_BLUE : 0)) |
|
||||
(pipe->color_write_mask_alpha[targetNum] ? D3D11_COLOR_WRITE_ENABLE_ALPHA : 0);
|
||||
}
|
||||
|
||||
void kinc_g4_pipeline_compile(struct kinc_g4_pipeline *state) {
|
||||
#ifndef KINC_KONG
|
||||
if (state->vertex_shader->impl.constantsSize > 0) {
|
||||
D3D11_BUFFER_DESC desc;
|
||||
desc.ByteWidth = (UINT)get_multiple_of_16(state->vertex_shader->impl.constantsSize);
|
||||
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.CPUAccessFlags = 0;
|
||||
desc.MiscFlags = 0;
|
||||
desc.StructureByteStride = 0;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateBuffer(dx_ctx.device, &desc, NULL, &state->impl.vertexConstantBuffer));
|
||||
}
|
||||
if (state->fragment_shader->impl.constantsSize > 0) {
|
||||
D3D11_BUFFER_DESC desc;
|
||||
desc.ByteWidth = (UINT)get_multiple_of_16(state->fragment_shader->impl.constantsSize);
|
||||
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.CPUAccessFlags = 0;
|
||||
desc.MiscFlags = 0;
|
||||
desc.StructureByteStride = 0;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateBuffer(dx_ctx.device, &desc, NULL, &state->impl.fragmentConstantBuffer));
|
||||
}
|
||||
if (state->geometry_shader != NULL && state->geometry_shader->impl.constantsSize > 0) {
|
||||
D3D11_BUFFER_DESC desc;
|
||||
desc.ByteWidth = (UINT)get_multiple_of_16(state->geometry_shader->impl.constantsSize);
|
||||
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.CPUAccessFlags = 0;
|
||||
desc.MiscFlags = 0;
|
||||
desc.StructureByteStride = 0;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateBuffer(dx_ctx.device, &desc, NULL, &state->impl.geometryConstantBuffer));
|
||||
}
|
||||
if (state->tessellation_control_shader != NULL && state->tessellation_control_shader->impl.constantsSize > 0) {
|
||||
D3D11_BUFFER_DESC desc;
|
||||
desc.ByteWidth = (UINT)get_multiple_of_16(state->tessellation_control_shader->impl.constantsSize);
|
||||
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.CPUAccessFlags = 0;
|
||||
desc.MiscFlags = 0;
|
||||
desc.StructureByteStride = 0;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateBuffer(dx_ctx.device, &desc, NULL, &state->impl.tessControlConstantBuffer));
|
||||
}
|
||||
if (state->tessellation_evaluation_shader != NULL && state->tessellation_evaluation_shader->impl.constantsSize > 0) {
|
||||
D3D11_BUFFER_DESC desc;
|
||||
desc.ByteWidth = (UINT)get_multiple_of_16(state->tessellation_evaluation_shader->impl.constantsSize);
|
||||
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.CPUAccessFlags = 0;
|
||||
desc.MiscFlags = 0;
|
||||
desc.StructureByteStride = 0;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateBuffer(dx_ctx.device, &desc, NULL, &state->impl.tessEvalConstantBuffer));
|
||||
}
|
||||
#endif
|
||||
|
||||
int all = 0;
|
||||
for (int stream = 0; state->input_layout[stream] != NULL; ++stream) {
|
||||
for (int index = 0; index < state->input_layout[stream]->size; ++index) {
|
||||
if (state->input_layout[stream]->elements[index].data == KINC_G4_VERTEX_DATA_F32_4X4) {
|
||||
all += 4;
|
||||
}
|
||||
else {
|
||||
all += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef KINC_KONG
|
||||
bool used[usedCount];
|
||||
for (int i = 0; i < usedCount; ++i)
|
||||
used[i] = false;
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
used[state->vertex_shader->impl.attributes[i].index] = true;
|
||||
}
|
||||
#endif
|
||||
stringCacheIndex = 0;
|
||||
D3D11_INPUT_ELEMENT_DESC *vertexDesc = (D3D11_INPUT_ELEMENT_DESC *)alloca(sizeof(D3D11_INPUT_ELEMENT_DESC) * all);
|
||||
|
||||
#ifdef KINC_KONG
|
||||
#define getAttributeLocation(a, b, c) index
|
||||
#endif
|
||||
|
||||
int i = 0;
|
||||
for (int stream = 0; state->input_layout[stream] != NULL; ++stream) {
|
||||
for (int index = 0; index < state->input_layout[stream]->size; ++index) {
|
||||
switch (state->input_layout[stream]->elements[index].data) {
|
||||
case KINC_G4_VERTEX_DATA_F32_1X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R32_FLOAT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_F32_2X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R32G32_FLOAT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_F32_3X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R32G32B32_FLOAT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_F32_4X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I8_1X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R8_SINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U8_1X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R8_UINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I8_1X_NORMALIZED:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R8_SNORM;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U8_1X_NORMALIZED:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R8_UNORM;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I8_2X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R8G8_SINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U8_2X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R8G8_UINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I8_2X_NORMALIZED:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R8G8_SNORM;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U8_2X_NORMALIZED:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R8G8_UNORM;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I8_4X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R8G8B8A8_SINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U8_4X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R8G8B8A8_UINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I8_4X_NORMALIZED:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R8G8B8A8_SNORM;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U8_4X_NORMALIZED:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I16_1X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R16_SINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U16_1X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R16_UINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I16_1X_NORMALIZED:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R16_SNORM;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U16_1X_NORMALIZED:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R16_UNORM;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I16_2X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R16G16_SINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U16_2X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R16G16_UINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I16_2X_NORMALIZED:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R16G16_SNORM;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U16_2X_NORMALIZED:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R16G16_UNORM;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I16_4X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R16G16B16A16_SINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U16_4X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R16G16B16A16_UINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I16_4X_NORMALIZED:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R16G16B16A16_SNORM;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U16_4X_NORMALIZED:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R16G16B16A16_UNORM;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I32_1X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R32_SINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U32_1X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R32_UINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I32_2X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R32G32_SINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U32_2X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R32G32_UINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I32_3X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R32G32B32_SINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U32_3X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R32G32B32_UINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I32_4X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R32G32B32A32_SINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U32_4X:
|
||||
setVertexDesc(&vertexDesc[i],
|
||||
getAttributeLocation(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name, used), index,
|
||||
stream, state->input_layout[stream]->instanced, -1);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R32G32B32A32_UINT;
|
||||
++i;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_F32_4X4: {
|
||||
char name[101];
|
||||
strcpy(name, state->input_layout[stream]->elements[index].name);
|
||||
strcat(name, "_");
|
||||
size_t length = strlen(name);
|
||||
sprintf(&name[length], "%i", 0);
|
||||
name[length + 1] = 0;
|
||||
int attributeLocation = getAttributeLocation(state->vertex_shader->impl.attributes, name, used);
|
||||
|
||||
for (int i2 = 0; i2 < 4; ++i2) {
|
||||
setVertexDesc(&vertexDesc[i], attributeLocation, index + i2, stream, state->input_layout[stream]->instanced, i2);
|
||||
vertexDesc[i].Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
++i;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateInputLayout(dx_ctx.device, vertexDesc, all, state->vertex_shader->impl.data,
|
||||
state->vertex_shader->impl.length, &state->impl.d3d11inputLayout));
|
||||
{
|
||||
D3D11_DEPTH_STENCIL_DESC desc;
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
|
||||
desc.DepthEnable = state->depth_mode != KINC_G4_COMPARE_ALWAYS;
|
||||
desc.DepthWriteMask = state->depth_write ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
|
||||
desc.DepthFunc = get_comparison(state->depth_mode);
|
||||
|
||||
desc.StencilEnable = state->stencil_front_mode != KINC_G4_COMPARE_ALWAYS || state->stencil_back_mode != KINC_G4_COMPARE_ALWAYS ||
|
||||
state->stencil_front_both_pass != KINC_G4_STENCIL_KEEP || state->stencil_back_both_pass != KINC_G4_STENCIL_KEEP ||
|
||||
state->stencil_front_depth_fail != KINC_G4_STENCIL_KEEP || state->stencil_back_depth_fail != KINC_G4_STENCIL_KEEP ||
|
||||
state->stencil_front_fail != KINC_G4_STENCIL_KEEP || state->stencil_back_fail != KINC_G4_STENCIL_KEEP;
|
||||
desc.StencilReadMask = state->stencil_read_mask;
|
||||
desc.StencilWriteMask = state->stencil_write_mask;
|
||||
desc.FrontFace.StencilFunc = desc.BackFace.StencilFunc = get_comparison(state->stencil_front_mode);
|
||||
desc.FrontFace.StencilDepthFailOp = desc.BackFace.StencilDepthFailOp = get_stencil_action(state->stencil_front_depth_fail);
|
||||
desc.FrontFace.StencilPassOp = desc.BackFace.StencilPassOp = get_stencil_action(state->stencil_front_both_pass);
|
||||
desc.FrontFace.StencilFailOp = desc.BackFace.StencilFailOp = get_stencil_action(state->stencil_front_fail);
|
||||
desc.BackFace.StencilFunc = desc.BackFace.StencilFunc = get_comparison(state->stencil_back_mode);
|
||||
desc.BackFace.StencilDepthFailOp = desc.BackFace.StencilDepthFailOp = get_stencil_action(state->stencil_back_depth_fail);
|
||||
desc.BackFace.StencilPassOp = desc.BackFace.StencilPassOp = get_stencil_action(state->stencil_back_both_pass);
|
||||
desc.BackFace.StencilFailOp = desc.BackFace.StencilFailOp = get_stencil_action(state->stencil_back_fail);
|
||||
|
||||
dx_ctx.device->lpVtbl->CreateDepthStencilState(dx_ctx.device, &desc, &state->impl.depthStencilState);
|
||||
}
|
||||
|
||||
{
|
||||
D3D11_RASTERIZER_DESC rasterDesc;
|
||||
rasterDesc.CullMode = convert_cull_mode(state->cull_mode);
|
||||
rasterDesc.FillMode = D3D11_FILL_SOLID;
|
||||
rasterDesc.FrontCounterClockwise = TRUE;
|
||||
rasterDesc.DepthBias = 0;
|
||||
rasterDesc.SlopeScaledDepthBias = 0.0f;
|
||||
rasterDesc.DepthBiasClamp = 0.0f;
|
||||
rasterDesc.DepthClipEnable = TRUE;
|
||||
rasterDesc.ScissorEnable = FALSE;
|
||||
rasterDesc.MultisampleEnable = FALSE;
|
||||
rasterDesc.AntialiasedLineEnable = FALSE;
|
||||
|
||||
dx_ctx.device->lpVtbl->CreateRasterizerState(dx_ctx.device, &rasterDesc, &state->impl.rasterizerState);
|
||||
rasterDesc.ScissorEnable = TRUE;
|
||||
dx_ctx.device->lpVtbl->CreateRasterizerState(dx_ctx.device, &rasterDesc, &state->impl.rasterizerStateScissor);
|
||||
|
||||
// We need d3d11_3 for conservative raster
|
||||
// D3D11_RASTERIZER_DESC2 rasterDesc;
|
||||
// rasterDesc.ConservativeRaster = conservativeRasterization ? D3D11_CONSERVATIVE_RASTERIZATION_MODE_ON : D3D11_CONSERVATIVE_RASTERIZATION_MODE_OFF;
|
||||
// dx_ctx.device->CreateRasterizerState2(&rasterDesc, &rasterizerState);
|
||||
// rasterDesc.ScissorEnable = TRUE;
|
||||
// dx_ctx.device->CreateRasterizerState2(&rasterDesc, &rasterizerStateScissor);
|
||||
}
|
||||
|
||||
{
|
||||
bool independentBlend = false;
|
||||
for (int i = 1; i < 8; ++i) {
|
||||
if (state->color_write_mask_red[0] != state->color_write_mask_red[i] || state->color_write_mask_green[0] != state->color_write_mask_green[i] ||
|
||||
state->color_write_mask_blue[0] != state->color_write_mask_blue[i] || state->color_write_mask_alpha[0] != state->color_write_mask_alpha[i]) {
|
||||
independentBlend = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
D3D11_BLEND_DESC blendDesc;
|
||||
memset(&blendDesc, 0, sizeof(blendDesc));
|
||||
blendDesc.AlphaToCoverageEnable = false;
|
||||
blendDesc.IndependentBlendEnable = independentBlend;
|
||||
|
||||
D3D11_RENDER_TARGET_BLEND_DESC rtbd[8];
|
||||
memset(&rtbd, 0, sizeof(rtbd));
|
||||
createRenderTargetBlendDesc(state, &rtbd[0], 0);
|
||||
blendDesc.RenderTarget[0] = rtbd[0];
|
||||
if (independentBlend) {
|
||||
for (int i = 1; i < 8; ++i) {
|
||||
createRenderTargetBlendDesc(state, &rtbd[i], i);
|
||||
blendDesc.RenderTarget[i] = rtbd[i];
|
||||
}
|
||||
}
|
||||
|
||||
dx_ctx.device->lpVtbl->CreateBlendState(dx_ctx.device, &blendDesc, &state->impl.blendState);
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ID3D11InputLayout;
|
||||
struct ID3D11PixelShader;
|
||||
struct ID3D11VertexShader;
|
||||
struct ID3D11Buffer;
|
||||
struct ID3D11DepthStencilState;
|
||||
struct ID3D11RasterizerState;
|
||||
struct ID3D11BlendState;
|
||||
|
||||
typedef struct {
|
||||
// PipelineStateImpl();
|
||||
//~PipelineStateImpl();
|
||||
struct ID3D11InputLayout *d3d11inputLayout;
|
||||
struct ID3D11Buffer *fragmentConstantBuffer;
|
||||
struct ID3D11Buffer *vertexConstantBuffer;
|
||||
struct ID3D11Buffer *geometryConstantBuffer;
|
||||
struct ID3D11Buffer *tessEvalConstantBuffer;
|
||||
struct ID3D11Buffer *tessControlConstantBuffer;
|
||||
struct ID3D11DepthStencilState *depthStencilState;
|
||||
struct ID3D11RasterizerState *rasterizerState;
|
||||
struct ID3D11RasterizerState *rasterizerStateScissor;
|
||||
struct ID3D11BlendState *blendState;
|
||||
// void set(Graphics4::PipelineState* pipeline, bool scissoring);
|
||||
// void setRasterizerState(bool scissoring);
|
||||
// static void setConstants();
|
||||
} kinc_g4_pipeline_impl_t;
|
||||
|
||||
void kinc_internal_set_constants(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,468 @@
|
||||
#include <kinc/error.h>
|
||||
#include <kinc/graphics4/rendertarget.h>
|
||||
#include <kinc/log.h>
|
||||
|
||||
static DXGI_FORMAT convertRenderTargetFormat(kinc_g4_render_target_format_t format) {
|
||||
switch (format) {
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_128BIT_FLOAT:
|
||||
return DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_64BIT_FLOAT:
|
||||
return DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_32BIT_RED_FLOAT:
|
||||
return DXGI_FORMAT_R32_FLOAT;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_16BIT_RED_FLOAT:
|
||||
return DXGI_FORMAT_R16_FLOAT;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_8BIT_RED:
|
||||
return DXGI_FORMAT_R8_UNORM;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_32BIT:
|
||||
default:
|
||||
return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
}
|
||||
}
|
||||
|
||||
static int formatRenderTargetByteSize(kinc_g4_render_target_format_t format) {
|
||||
switch (format) {
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_128BIT_FLOAT:
|
||||
return 16;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_64BIT_FLOAT:
|
||||
return 8;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_32BIT_RED_FLOAT:
|
||||
return 4;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_16BIT_RED_FLOAT:
|
||||
return 2;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_8BIT_RED:
|
||||
return 1;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_32BIT:
|
||||
default:
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_init_with_multisampling(kinc_g4_render_target_t *renderTarget, int width, int height, kinc_g4_render_target_format_t format,
|
||||
int depthBufferBits, int stencilBufferBits, int samples_per_pixel) {
|
||||
renderTarget->isCubeMap = false;
|
||||
renderTarget->isDepthAttachment = false;
|
||||
renderTarget->texWidth = renderTarget->width = width;
|
||||
renderTarget->texHeight = renderTarget->height = height;
|
||||
renderTarget->impl.format = format;
|
||||
renderTarget->impl.textureStaging = NULL;
|
||||
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
desc.Width = width;
|
||||
desc.Height = height;
|
||||
desc.MipLevels = desc.ArraySize = 1;
|
||||
desc.Format = convertRenderTargetFormat(format);
|
||||
if (format == KINC_G4_RENDER_TARGET_FORMAT_16BIT_DEPTH) {
|
||||
renderTarget->isDepthAttachment = true;
|
||||
depthBufferBits = 16;
|
||||
stencilBufferBits = 0;
|
||||
}
|
||||
|
||||
bool antialiasing = samples_per_pixel > 1;
|
||||
if (antialiasing) {
|
||||
desc.SampleDesc.Count = samples_per_pixel;
|
||||
desc.SampleDesc.Quality = D3D11_STANDARD_MULTISAMPLE_PATTERN;
|
||||
}
|
||||
else {
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
}
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.CPUAccessFlags = 0; // D3D11_CPU_ACCESS_WRITE;
|
||||
desc.MiscFlags = 0;
|
||||
|
||||
renderTarget->impl.textureRender = NULL;
|
||||
renderTarget->impl.textureSample = NULL;
|
||||
renderTarget->impl.renderTargetSRV = NULL;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
renderTarget->impl.renderTargetViewRender[i] = NULL;
|
||||
renderTarget->impl.renderTargetViewSample[i] = NULL;
|
||||
}
|
||||
if (!renderTarget->isDepthAttachment) {
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &desc, NULL, &renderTarget->impl.textureRender));
|
||||
|
||||
D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
|
||||
renderTargetViewDesc.Format = desc.Format;
|
||||
renderTargetViewDesc.ViewDimension = antialiasing ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
|
||||
renderTargetViewDesc.Texture2D.MipSlice = 0;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateRenderTargetView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.textureRender,
|
||||
&renderTargetViewDesc, &renderTarget->impl.renderTargetViewRender[0]));
|
||||
|
||||
if (antialiasing) {
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &desc, NULL, &renderTarget->impl.textureSample));
|
||||
|
||||
D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
|
||||
renderTargetViewDesc.Format = desc.Format;
|
||||
renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
|
||||
renderTargetViewDesc.Texture2D.MipSlice = 0;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateRenderTargetView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.textureSample,
|
||||
&renderTargetViewDesc, &renderTarget->impl.renderTargetViewSample[0]));
|
||||
}
|
||||
else {
|
||||
renderTarget->impl.textureSample = renderTarget->impl.textureRender;
|
||||
renderTarget->impl.renderTargetViewSample[0] = renderTarget->impl.renderTargetViewRender[0];
|
||||
}
|
||||
}
|
||||
|
||||
renderTarget->impl.depthStencil = NULL;
|
||||
renderTarget->impl.depthStencilSRV = NULL;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
renderTarget->impl.depthStencilView[i] = NULL;
|
||||
}
|
||||
|
||||
DXGI_FORMAT depthFormat;
|
||||
DXGI_FORMAT depthViewFormat;
|
||||
DXGI_FORMAT depthResourceFormat;
|
||||
if (depthBufferBits == 16 && stencilBufferBits == 0) {
|
||||
depthFormat = DXGI_FORMAT_R16_TYPELESS;
|
||||
depthViewFormat = DXGI_FORMAT_D16_UNORM;
|
||||
depthResourceFormat = DXGI_FORMAT_R16_UNORM;
|
||||
}
|
||||
else {
|
||||
depthFormat = DXGI_FORMAT_R24G8_TYPELESS;
|
||||
depthViewFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
|
||||
depthResourceFormat = DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
|
||||
}
|
||||
|
||||
if (depthBufferBits > 0) {
|
||||
D3D11_TEXTURE2D_DESC depthStencilDesc;
|
||||
depthStencilDesc.Format = depthFormat;
|
||||
depthStencilDesc.Width = width;
|
||||
depthStencilDesc.Height = height;
|
||||
depthStencilDesc.ArraySize = 1;
|
||||
depthStencilDesc.MipLevels = 1;
|
||||
depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
|
||||
depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
depthStencilDesc.CPUAccessFlags = 0;
|
||||
depthStencilDesc.MiscFlags = 0;
|
||||
if (antialiasing) {
|
||||
depthStencilDesc.SampleDesc.Count = 4;
|
||||
depthStencilDesc.SampleDesc.Quality = D3D11_STANDARD_MULTISAMPLE_PATTERN;
|
||||
}
|
||||
else {
|
||||
depthStencilDesc.SampleDesc.Count = 1;
|
||||
depthStencilDesc.SampleDesc.Quality = 0;
|
||||
}
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &depthStencilDesc, NULL, &renderTarget->impl.depthStencil));
|
||||
D3D11_DEPTH_STENCIL_VIEW_DESC viewDesc;
|
||||
viewDesc.Format = depthViewFormat;
|
||||
viewDesc.ViewDimension = antialiasing ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D;
|
||||
viewDesc.Flags = 0;
|
||||
if (!antialiasing) {
|
||||
viewDesc.Texture2D.MipSlice = 0;
|
||||
}
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateDepthStencilView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.depthStencil, &viewDesc,
|
||||
&renderTarget->impl.depthStencilView[0]));
|
||||
}
|
||||
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc;
|
||||
if (!renderTarget->isDepthAttachment) {
|
||||
shaderResourceViewDesc.Format = desc.Format;
|
||||
shaderResourceViewDesc.ViewDimension = antialiasing ? D3D11_SRV_DIMENSION_TEXTURE2DMS : D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
shaderResourceViewDesc.Texture2D.MostDetailedMip = 0;
|
||||
shaderResourceViewDesc.Texture2D.MipLevels = 1;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateShaderResourceView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.textureSample,
|
||||
&shaderResourceViewDesc, &renderTarget->impl.renderTargetSRV));
|
||||
}
|
||||
|
||||
if (depthBufferBits > 0) {
|
||||
shaderResourceViewDesc.Format = depthResourceFormat;
|
||||
shaderResourceViewDesc.ViewDimension = antialiasing ? D3D11_SRV_DIMENSION_TEXTURE2DMS : D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
shaderResourceViewDesc.Texture2D.MostDetailedMip = 0;
|
||||
shaderResourceViewDesc.Texture2D.MipLevels = 1;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateShaderResourceView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.depthStencil,
|
||||
&shaderResourceViewDesc, &renderTarget->impl.depthStencilSRV));
|
||||
}
|
||||
|
||||
if (renderTarget->impl.renderTargetViewRender[0] != NULL) {
|
||||
FLOAT colors[4] = {0, 0, 0, 0};
|
||||
dx_ctx.context->lpVtbl->ClearRenderTargetView(dx_ctx.context, renderTarget->impl.renderTargetViewRender[0], colors);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_init_cube_with_multisampling(kinc_g4_render_target_t *renderTarget, int cubeMapSize, kinc_g4_render_target_format_t format,
|
||||
int depthBufferBits, int stencilBufferBits, int samples_per_pixel) {
|
||||
renderTarget->width = cubeMapSize;
|
||||
renderTarget->height = cubeMapSize;
|
||||
renderTarget->isCubeMap = true;
|
||||
renderTarget->isDepthAttachment = false;
|
||||
|
||||
renderTarget->texWidth = renderTarget->width;
|
||||
renderTarget->texHeight = renderTarget->height;
|
||||
renderTarget->impl.format = format;
|
||||
renderTarget->impl.textureStaging = NULL;
|
||||
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
desc.Width = renderTarget->width;
|
||||
desc.Height = renderTarget->height;
|
||||
desc.MipLevels = 1;
|
||||
desc.ArraySize = 6;
|
||||
desc.Format = convertRenderTargetFormat(format);
|
||||
if (format == KINC_G4_RENDER_TARGET_FORMAT_16BIT_DEPTH) {
|
||||
renderTarget->isDepthAttachment = true;
|
||||
depthBufferBits = 16;
|
||||
stencilBufferBits = 0;
|
||||
}
|
||||
|
||||
bool antialiasing = samples_per_pixel > 1;
|
||||
if (antialiasing) {
|
||||
desc.SampleDesc.Count = samples_per_pixel;
|
||||
desc.SampleDesc.Quality = D3D11_STANDARD_MULTISAMPLE_PATTERN;
|
||||
}
|
||||
else {
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
}
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.CPUAccessFlags = 0; // D3D11_CPU_ACCESS_WRITE;
|
||||
desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
|
||||
|
||||
renderTarget->impl.textureRender = NULL;
|
||||
renderTarget->impl.textureSample = NULL;
|
||||
renderTarget->impl.renderTargetSRV = NULL;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
renderTarget->impl.renderTargetViewRender[i] = NULL;
|
||||
renderTarget->impl.renderTargetViewSample[i] = NULL;
|
||||
}
|
||||
if (!renderTarget->isDepthAttachment) {
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &desc, NULL, &renderTarget->impl.textureRender));
|
||||
|
||||
D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
|
||||
renderTargetViewDesc.Format = desc.Format;
|
||||
renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
|
||||
renderTargetViewDesc.Texture2DArray.MipSlice = 0;
|
||||
renderTargetViewDesc.Texture2DArray.ArraySize = 1;
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
renderTargetViewDesc.Texture2DArray.FirstArraySlice = i;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateRenderTargetView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.textureRender,
|
||||
&renderTargetViewDesc, &renderTarget->impl.renderTargetViewRender[i]));
|
||||
}
|
||||
|
||||
if (antialiasing) {
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &desc, NULL, &renderTarget->impl.textureSample));
|
||||
|
||||
D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
|
||||
renderTargetViewDesc.Format = desc.Format;
|
||||
renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
|
||||
renderTargetViewDesc.Texture2D.MipSlice = 0;
|
||||
renderTargetViewDesc.Texture2DArray.ArraySize = 1;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
renderTargetViewDesc.Texture2DArray.FirstArraySlice = i;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateRenderTargetView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.textureSample,
|
||||
&renderTargetViewDesc, &renderTarget->impl.renderTargetViewSample[i]));
|
||||
}
|
||||
}
|
||||
else {
|
||||
renderTarget->impl.textureSample = renderTarget->impl.textureRender;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
renderTarget->impl.renderTargetViewSample[i] = renderTarget->impl.renderTargetViewRender[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
renderTarget->impl.depthStencil = NULL;
|
||||
renderTarget->impl.depthStencilSRV = NULL;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
renderTarget->impl.depthStencilView[i] = NULL;
|
||||
}
|
||||
|
||||
DXGI_FORMAT depthFormat;
|
||||
DXGI_FORMAT depthViewFormat;
|
||||
DXGI_FORMAT depthResourceFormat;
|
||||
if (depthBufferBits == 16 && stencilBufferBits == 0) {
|
||||
depthFormat = DXGI_FORMAT_R16_TYPELESS;
|
||||
depthViewFormat = DXGI_FORMAT_D16_UNORM;
|
||||
depthResourceFormat = DXGI_FORMAT_R16_UNORM;
|
||||
}
|
||||
else {
|
||||
depthFormat = DXGI_FORMAT_R24G8_TYPELESS;
|
||||
depthViewFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
|
||||
depthResourceFormat = DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
|
||||
}
|
||||
|
||||
if (depthBufferBits > 0) {
|
||||
D3D11_TEXTURE2D_DESC depthStencilDesc;
|
||||
depthStencilDesc.Format = depthFormat;
|
||||
depthStencilDesc.Width = renderTarget->width;
|
||||
depthStencilDesc.Height = renderTarget->height;
|
||||
depthStencilDesc.ArraySize = 1;
|
||||
depthStencilDesc.MipLevels = 1;
|
||||
depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
|
||||
depthStencilDesc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
|
||||
depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
depthStencilDesc.CPUAccessFlags = 0;
|
||||
depthStencilDesc.ArraySize = 6;
|
||||
if (antialiasing) {
|
||||
depthStencilDesc.SampleDesc.Count = 4;
|
||||
depthStencilDesc.SampleDesc.Quality = D3D11_STANDARD_MULTISAMPLE_PATTERN;
|
||||
}
|
||||
else {
|
||||
depthStencilDesc.SampleDesc.Count = 1;
|
||||
depthStencilDesc.SampleDesc.Quality = 0;
|
||||
}
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &depthStencilDesc, NULL, &renderTarget->impl.depthStencil));
|
||||
|
||||
D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc;
|
||||
depthStencilViewDesc.Format = depthViewFormat;
|
||||
depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
|
||||
depthStencilViewDesc.Texture2DArray.MipSlice = 0;
|
||||
depthStencilViewDesc.Texture2DArray.ArraySize = 1;
|
||||
depthStencilViewDesc.Flags = 0;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
depthStencilViewDesc.Texture2DArray.FirstArraySlice = i;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateDepthStencilView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.depthStencil,
|
||||
&depthStencilViewDesc, &renderTarget->impl.depthStencilView[i]));
|
||||
}
|
||||
}
|
||||
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc;
|
||||
if (!renderTarget->isDepthAttachment) {
|
||||
shaderResourceViewDesc.Format = desc.Format;
|
||||
shaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
|
||||
shaderResourceViewDesc.TextureCube.MostDetailedMip = 0;
|
||||
shaderResourceViewDesc.TextureCube.MipLevels = 1;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateShaderResourceView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.textureSample,
|
||||
&shaderResourceViewDesc, &renderTarget->impl.renderTargetSRV));
|
||||
}
|
||||
|
||||
if (depthBufferBits > 0) {
|
||||
shaderResourceViewDesc.Format = depthResourceFormat;
|
||||
shaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
|
||||
shaderResourceViewDesc.TextureCube.MostDetailedMip = 0;
|
||||
shaderResourceViewDesc.TextureCube.MipLevels = 1;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateShaderResourceView(dx_ctx.device, (ID3D11Resource *)renderTarget->impl.depthStencil,
|
||||
&shaderResourceViewDesc, &renderTarget->impl.depthStencilSRV));
|
||||
}
|
||||
|
||||
if (!renderTarget->isDepthAttachment) {
|
||||
FLOAT colors[4] = {0, 0, 0, 0};
|
||||
for (int i = 0; i < 6; i++) {
|
||||
dx_ctx.context->lpVtbl->ClearRenderTargetView(dx_ctx.context, renderTarget->impl.renderTargetViewRender[i], colors);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_destroy(kinc_g4_render_target_t *renderTarget) {
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (renderTarget->impl.renderTargetViewRender[i] != NULL)
|
||||
renderTarget->impl.renderTargetViewRender[i]->lpVtbl->Release(renderTarget->impl.renderTargetViewRender[i]);
|
||||
if (renderTarget->impl.renderTargetViewSample[i] != NULL &&
|
||||
renderTarget->impl.renderTargetViewSample[i] != renderTarget->impl.renderTargetViewRender[i])
|
||||
renderTarget->impl.renderTargetViewSample[i]->lpVtbl->Release(renderTarget->impl.renderTargetViewSample[i]);
|
||||
if (renderTarget->impl.depthStencilView[i] != NULL)
|
||||
renderTarget->impl.depthStencilView[i]->lpVtbl->Release(renderTarget->impl.depthStencilView[i]);
|
||||
}
|
||||
if (renderTarget->impl.renderTargetSRV != NULL)
|
||||
renderTarget->impl.renderTargetSRV->lpVtbl->Release(renderTarget->impl.renderTargetSRV);
|
||||
if (renderTarget->impl.depthStencilSRV != NULL)
|
||||
renderTarget->impl.depthStencilSRV->lpVtbl->Release(renderTarget->impl.depthStencilSRV);
|
||||
if (renderTarget->impl.depthStencil != NULL)
|
||||
renderTarget->impl.depthStencil->lpVtbl->Release(renderTarget->impl.depthStencil);
|
||||
if (renderTarget->impl.textureRender != NULL)
|
||||
renderTarget->impl.textureRender->lpVtbl->Release(renderTarget->impl.textureRender);
|
||||
if (renderTarget->impl.textureStaging != NULL)
|
||||
renderTarget->impl.textureStaging->lpVtbl->Release(renderTarget->impl.textureStaging);
|
||||
if (renderTarget->impl.textureSample != NULL && renderTarget->impl.textureSample != renderTarget->impl.textureRender)
|
||||
renderTarget->impl.textureSample->lpVtbl->Release(renderTarget->impl.textureSample);
|
||||
}
|
||||
|
||||
#ifdef KINC_KONG
|
||||
void kinc_g4_render_target_use_color_as_texture(kinc_g4_render_target_t *renderTarget, uint32_t unit) {
|
||||
if (renderTarget->impl.textureSample != renderTarget->impl.textureRender) {
|
||||
dx_ctx.context->lpVtbl->ResolveSubresource(dx_ctx.context, (ID3D11Resource *)renderTarget->impl.textureSample, 0,
|
||||
(ID3D11Resource *)renderTarget->impl.textureRender, 0, DXGI_FORMAT_R8G8B8A8_UNORM);
|
||||
}
|
||||
|
||||
dx_ctx.context->lpVtbl->PSSetShaderResources(dx_ctx.context, unit, 1,
|
||||
renderTarget->isDepthAttachment ? &renderTarget->impl.depthStencilSRV : &renderTarget->impl.renderTargetSRV);
|
||||
}
|
||||
#else
|
||||
void kinc_g4_render_target_use_color_as_texture(kinc_g4_render_target_t *renderTarget, kinc_g4_texture_unit_t unit) {
|
||||
if (unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] < 0 && unit.stages[KINC_G4_SHADER_TYPE_VERTEX] < 0)
|
||||
return;
|
||||
|
||||
if (renderTarget->impl.textureSample != renderTarget->impl.textureRender) {
|
||||
dx_ctx.context->lpVtbl->ResolveSubresource(dx_ctx.context, (ID3D11Resource *)renderTarget->impl.textureSample, 0,
|
||||
(ID3D11Resource *)renderTarget->impl.textureRender, 0, DXGI_FORMAT_R8G8B8A8_UNORM);
|
||||
}
|
||||
|
||||
if (unit.stages[KINC_G4_SHADER_TYPE_VERTEX] >= 0) {
|
||||
dx_ctx.context->lpVtbl->VSSetShaderResources(dx_ctx.context, unit.stages[KINC_G4_SHADER_TYPE_VERTEX], 1,
|
||||
renderTarget->isDepthAttachment ? &renderTarget->impl.depthStencilSRV
|
||||
: &renderTarget->impl.renderTargetSRV);
|
||||
}
|
||||
|
||||
if (unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] >= 0) {
|
||||
dx_ctx.context->lpVtbl->PSSetShaderResources(dx_ctx.context, unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], 1,
|
||||
renderTarget->isDepthAttachment ? &renderTarget->impl.depthStencilSRV
|
||||
: &renderTarget->impl.renderTargetSRV);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void kinc_g4_render_target_use_depth_as_texture(kinc_g4_render_target_t *renderTarget, kinc_g4_texture_unit_t unit) {
|
||||
if (unit.stages[KINC_G4_SHADER_TYPE_VERTEX] >= 0) {
|
||||
dx_ctx.context->lpVtbl->VSSetShaderResources(dx_ctx.context, unit.stages[KINC_G4_SHADER_TYPE_VERTEX], 1, &renderTarget->impl.depthStencilSRV);
|
||||
}
|
||||
|
||||
if (unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] >= 0) {
|
||||
dx_ctx.context->lpVtbl->PSSetShaderResources(dx_ctx.context, unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], 1, &renderTarget->impl.depthStencilSRV);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_set_depth_stencil_from(kinc_g4_render_target_t *renderTarget, kinc_g4_render_target_t *source) {
|
||||
renderTarget->impl.depthStencil = source->impl.depthStencil;
|
||||
for (int i = 0; i < 6; i++) {
|
||||
renderTarget->impl.depthStencilView[i] = source->impl.depthStencilView[i];
|
||||
}
|
||||
renderTarget->impl.depthStencilSRV = source->impl.depthStencilSRV;
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_get_pixels(kinc_g4_render_target_t *renderTarget, uint8_t *data) {
|
||||
if (renderTarget->impl.textureStaging == NULL) {
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
desc.Width = renderTarget->texWidth;
|
||||
desc.Height = renderTarget->texHeight;
|
||||
desc.MipLevels = 1;
|
||||
desc.ArraySize = 1;
|
||||
desc.Format = convertRenderTargetFormat((kinc_g4_render_target_format_t)renderTarget->impl.format);
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Usage = D3D11_USAGE_STAGING;
|
||||
desc.BindFlags = 0;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
|
||||
desc.MiscFlags = 0;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &desc, NULL, &renderTarget->impl.textureStaging));
|
||||
}
|
||||
|
||||
D3D11_BOX sourceRegion;
|
||||
sourceRegion.left = 0;
|
||||
sourceRegion.right = renderTarget->texWidth;
|
||||
sourceRegion.top = 0;
|
||||
sourceRegion.bottom = renderTarget->texHeight;
|
||||
sourceRegion.front = 0;
|
||||
sourceRegion.back = 1;
|
||||
dx_ctx.context->lpVtbl->CopySubresourceRegion(dx_ctx.context, (ID3D11Resource *)renderTarget->impl.textureStaging, 0, 0, 0, 0,
|
||||
(ID3D11Resource *)renderTarget->impl.textureRender, 0, &sourceRegion);
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE mappedResource;
|
||||
dx_ctx.context->lpVtbl->Map(dx_ctx.context, (ID3D11Resource *)renderTarget->impl.textureStaging, 0, D3D11_MAP_READ, 0, &mappedResource);
|
||||
int size;
|
||||
if (mappedResource.RowPitch != 0) {
|
||||
size = mappedResource.RowPitch * renderTarget->texHeight;
|
||||
}
|
||||
else {
|
||||
size = renderTarget->texWidth * renderTarget->texHeight * formatRenderTargetByteSize((kinc_g4_render_target_format_t)renderTarget->impl.format);
|
||||
}
|
||||
memcpy(data, mappedResource.pData, size);
|
||||
dx_ctx.context->lpVtbl->Unmap(dx_ctx.context, (ID3D11Resource *)renderTarget->impl.textureStaging, 0);
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_generate_mipmaps(kinc_g4_render_target_t *renderTarget, int levels) {}
|
@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ID3D11Texture2D;
|
||||
struct ID3D11RenderTargetView;
|
||||
struct ID3D11DepthStencilView;
|
||||
struct ID3D11ShaderResourceView;
|
||||
|
||||
typedef struct {
|
||||
struct ID3D11Texture2D *textureRender;
|
||||
struct ID3D11Texture2D *textureSample;
|
||||
struct ID3D11Texture2D *textureStaging;
|
||||
struct ID3D11RenderTargetView *renderTargetViewRender[6];
|
||||
struct ID3D11RenderTargetView *renderTargetViewSample[6];
|
||||
struct ID3D11Texture2D *depthStencil;
|
||||
struct ID3D11DepthStencilView *depthStencilView[6];
|
||||
struct ID3D11ShaderResourceView *renderTargetSRV;
|
||||
struct ID3D11ShaderResourceView *depthStencilSRV;
|
||||
int format;
|
||||
} kinc_g4_render_target_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,114 @@
|
||||
#include <kinc/graphics4/shader.h>
|
||||
|
||||
void kinc_g4_shader_destroy(kinc_g4_shader_t *shader) {
|
||||
if (shader->impl.shader != NULL) {
|
||||
((IUnknown *)shader->impl.shader)->lpVtbl->Release(shader->impl.shader);
|
||||
free(shader->impl.data);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_shader_init(kinc_g4_shader_t *shader, const void *_data, size_t length, kinc_g4_shader_type_t type) {
|
||||
unsigned index = 0;
|
||||
uint8_t *data = (uint8_t *)_data;
|
||||
shader->impl.type = (int)type;
|
||||
|
||||
#ifndef KINC_KONG
|
||||
memset(&shader->impl.attributes, 0, sizeof(shader->impl.attributes));
|
||||
int attributesCount = data[index++];
|
||||
for (int i = 0; i < attributesCount; ++i) {
|
||||
unsigned char name[256];
|
||||
for (unsigned i2 = 0; i2 < 255; ++i2) {
|
||||
name[i2] = data[index++];
|
||||
if (name[i2] == 0)
|
||||
break;
|
||||
}
|
||||
shader->impl.attributes[i].hash = kinc_internal_hash_name(name);
|
||||
shader->impl.attributes[i].index = data[index++];
|
||||
}
|
||||
|
||||
memset(&shader->impl.textures, 0, sizeof(shader->impl.textures));
|
||||
uint8_t texCount = data[index++];
|
||||
for (unsigned i = 0; i < texCount; ++i) {
|
||||
unsigned char name[256];
|
||||
for (unsigned i2 = 0; i2 < 255; ++i2) {
|
||||
name[i2] = data[index++];
|
||||
if (name[i2] == 0)
|
||||
break;
|
||||
}
|
||||
shader->impl.textures[i].hash = kinc_internal_hash_name(name);
|
||||
shader->impl.textures[i].index = data[index++];
|
||||
}
|
||||
|
||||
memset(&shader->impl.constants, 0, sizeof(shader->impl.constants));
|
||||
uint8_t constantCount = data[index++];
|
||||
shader->impl.constantsSize = 0;
|
||||
for (unsigned i = 0; i < constantCount; ++i) {
|
||||
unsigned char name[256];
|
||||
for (unsigned i2 = 0; i2 < 255; ++i2) {
|
||||
name[i2] = data[index++];
|
||||
if (name[i2] == 0)
|
||||
break;
|
||||
}
|
||||
kinc_internal_shader_constant_t constant;
|
||||
constant.hash = kinc_internal_hash_name(name);
|
||||
constant.offset = *(uint32_t *)&data[index];
|
||||
index += 4;
|
||||
constant.size = *(uint32_t *)&data[index];
|
||||
index += 4;
|
||||
constant.columns = data[index];
|
||||
index += 1;
|
||||
constant.rows = data[index];
|
||||
index += 1;
|
||||
|
||||
shader->impl.constants[i] = constant;
|
||||
shader->impl.constantsSize = constant.offset + constant.size;
|
||||
}
|
||||
#endif
|
||||
|
||||
shader->impl.length = (int)(length - index);
|
||||
shader->impl.data = (uint8_t *)malloc(shader->impl.length);
|
||||
assert(shader->impl.data != NULL);
|
||||
memcpy(shader->impl.data, &data[index], shader->impl.length);
|
||||
|
||||
switch (type) {
|
||||
case KINC_G4_SHADER_TYPE_VERTEX:
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateVertexShader(dx_ctx.device, shader->impl.data, shader->impl.length, NULL,
|
||||
(ID3D11VertexShader **)&shader->impl.shader));
|
||||
break;
|
||||
case KINC_G4_SHADER_TYPE_FRAGMENT:
|
||||
kinc_microsoft_affirm(
|
||||
dx_ctx.device->lpVtbl->CreatePixelShader(dx_ctx.device, shader->impl.data, shader->impl.length, NULL, (ID3D11PixelShader **)&shader->impl.shader));
|
||||
break;
|
||||
case KINC_G4_SHADER_TYPE_GEOMETRY:
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateGeometryShader(dx_ctx.device, shader->impl.data, shader->impl.length, NULL,
|
||||
(ID3D11GeometryShader **)&shader->impl.shader));
|
||||
break;
|
||||
case KINC_G4_SHADER_TYPE_TESSELLATION_CONTROL:
|
||||
kinc_microsoft_affirm(
|
||||
dx_ctx.device->lpVtbl->CreateHullShader(dx_ctx.device, shader->impl.data, shader->impl.length, NULL, (ID3D11HullShader **)&shader->impl.shader));
|
||||
break;
|
||||
case KINC_G4_SHADER_TYPE_TESSELLATION_EVALUATION:
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateDomainShader(dx_ctx.device, shader->impl.data, shader->impl.length, NULL,
|
||||
(ID3D11DomainShader **)&shader->impl.shader));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef KRAFIX_LIBRARY
|
||||
extern int krafix_compile(const char *source, char *output, int *length, const char *targetlang, const char *system, const char *shadertype, int version);
|
||||
#endif
|
||||
|
||||
int kinc_g4_shader_init_from_source(kinc_g4_shader_t *shader, const char *source, kinc_g4_shader_type_t type) {
|
||||
#ifdef KRAFIX_LIBRARY
|
||||
char *output = malloc(1024 * 1024);
|
||||
int length;
|
||||
int errors = krafix_compile(source, output, &length, "d3d11", "windows", type == KINC_G4_SHADER_TYPE_FRAGMENT ? "frag" : "vert", -1);
|
||||
if (errors > 0) {
|
||||
return errors;
|
||||
}
|
||||
kinc_g4_shader_init(shader, output, length, type);
|
||||
return 0;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <kinc/backend/graphics4/ShaderHash.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint32_t hash;
|
||||
uint32_t offset;
|
||||
uint32_t size;
|
||||
uint8_t columns;
|
||||
uint8_t rows;
|
||||
} kinc_internal_shader_constant_t;
|
||||
|
||||
typedef struct {
|
||||
#ifndef KINC_KONG
|
||||
kinc_internal_shader_constant_t constants[64];
|
||||
int constantsSize;
|
||||
kinc_internal_hash_index_t attributes[64];
|
||||
kinc_internal_hash_index_t textures[64];
|
||||
#endif
|
||||
void *shader;
|
||||
uint8_t *data;
|
||||
int length;
|
||||
int type;
|
||||
} kinc_g4_shader_impl_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t vertexOffset;
|
||||
uint32_t vertexSize;
|
||||
uint32_t fragmentOffset;
|
||||
uint32_t fragmentSize;
|
||||
uint32_t geometryOffset;
|
||||
uint32_t geometrySize;
|
||||
uint32_t tessEvalOffset;
|
||||
uint32_t tessEvalSize;
|
||||
uint32_t tessControlOffset;
|
||||
uint32_t tessControlSize;
|
||||
uint8_t vertexColumns;
|
||||
uint8_t vertexRows;
|
||||
uint8_t fragmentColumns;
|
||||
uint8_t fragmentRows;
|
||||
uint8_t geometryColumns;
|
||||
uint8_t geometryRows;
|
||||
uint8_t tessEvalColumns;
|
||||
uint8_t tessEvalRows;
|
||||
uint8_t tessControlColumns;
|
||||
uint8_t tessControlRows;
|
||||
} kinc_g4_constant_location_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,353 @@
|
||||
#include <kinc/graphics4/texture.h>
|
||||
#include <kinc/graphics4/textureunit.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
static kinc_g4_texture_t *setTextures[16] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
|
||||
static DXGI_FORMAT convertFormat(kinc_image_format_t format) {
|
||||
switch (format) {
|
||||
case KINC_IMAGE_FORMAT_RGBA128:
|
||||
return DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
case KINC_IMAGE_FORMAT_RGBA64:
|
||||
return DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||
case KINC_IMAGE_FORMAT_RGB24:
|
||||
return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
case KINC_IMAGE_FORMAT_A32:
|
||||
return DXGI_FORMAT_R32_FLOAT;
|
||||
case KINC_IMAGE_FORMAT_A16:
|
||||
return DXGI_FORMAT_R16_FLOAT;
|
||||
case KINC_IMAGE_FORMAT_GREY8:
|
||||
return DXGI_FORMAT_R8_UNORM;
|
||||
case KINC_IMAGE_FORMAT_BGRA32:
|
||||
return DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
case KINC_IMAGE_FORMAT_RGBA32:
|
||||
return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
default:
|
||||
assert(false);
|
||||
return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
}
|
||||
}
|
||||
|
||||
static int formatByteSize(kinc_image_format_t format) {
|
||||
switch (format) {
|
||||
case KINC_IMAGE_FORMAT_RGBA128:
|
||||
return 16;
|
||||
case KINC_IMAGE_FORMAT_RGBA64:
|
||||
return 8;
|
||||
case KINC_IMAGE_FORMAT_RGB24:
|
||||
return 4;
|
||||
case KINC_IMAGE_FORMAT_A32:
|
||||
return 4;
|
||||
case KINC_IMAGE_FORMAT_A16:
|
||||
return 2;
|
||||
case KINC_IMAGE_FORMAT_GREY8:
|
||||
return 1;
|
||||
case KINC_IMAGE_FORMAT_BGRA32:
|
||||
case KINC_IMAGE_FORMAT_RGBA32:
|
||||
return 4;
|
||||
default:
|
||||
assert(false);
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
static bool isHdr(kinc_image_format_t format) {
|
||||
return format == KINC_IMAGE_FORMAT_RGBA128 || format == KINC_IMAGE_FORMAT_RGBA64 || format == KINC_IMAGE_FORMAT_A32 || format == KINC_IMAGE_FORMAT_A16;
|
||||
}
|
||||
|
||||
void kinc_g4_texture_init_from_image(kinc_g4_texture_t *texture, kinc_image_t *image) {
|
||||
memset(&texture->impl, 0, sizeof(texture->impl));
|
||||
texture->impl.stage = 0;
|
||||
texture->tex_width = image->width;
|
||||
texture->tex_height = image->height;
|
||||
texture->tex_depth = 1;
|
||||
texture->format = image->format;
|
||||
texture->impl.rowPitch = 0;
|
||||
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
desc.Width = image->width;
|
||||
desc.Height = image->height;
|
||||
desc.MipLevels = desc.ArraySize = 1;
|
||||
desc.Format = convertFormat(image->format);
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.CPUAccessFlags = 0; // D3D11_CPU_ACCESS_WRITE;
|
||||
desc.MiscFlags = 0;
|
||||
|
||||
D3D11_SUBRESOURCE_DATA data;
|
||||
data.pSysMem = image->data;
|
||||
data.SysMemPitch = image->width * formatByteSize(image->format);
|
||||
data.SysMemSlicePitch = 0;
|
||||
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &desc, &data, &texture->impl.texture));
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateShaderResourceView(dx_ctx.device, (ID3D11Resource *)texture->impl.texture, NULL, &texture->impl.view));
|
||||
}
|
||||
|
||||
void kinc_g4_texture_init_from_image3d(kinc_g4_texture_t *texture, kinc_image_t *image) {
|
||||
memset(&texture->impl, 0, sizeof(texture->impl));
|
||||
texture->impl.stage = 0;
|
||||
texture->tex_width = image->width;
|
||||
texture->tex_height = image->height;
|
||||
texture->tex_depth = image->depth;
|
||||
texture->format = image->format;
|
||||
texture->impl.rowPitch = 0;
|
||||
|
||||
D3D11_TEXTURE3D_DESC desc;
|
||||
desc.Width = image->width;
|
||||
desc.Height = image->height;
|
||||
desc.Depth = image->depth;
|
||||
desc.MipLevels = 1;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.MiscFlags = 0;
|
||||
desc.Format = convertFormat(image->format);
|
||||
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.CPUAccessFlags = 0;
|
||||
|
||||
D3D11_SUBRESOURCE_DATA data;
|
||||
data.pSysMem = image->data;
|
||||
data.SysMemPitch = image->width * formatByteSize(image->format);
|
||||
data.SysMemSlicePitch = image->width * image->height * formatByteSize(image->format);
|
||||
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture3D(dx_ctx.device, &desc, &data, &texture->impl.texture3D));
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateShaderResourceView(dx_ctx.device, (ID3D11Resource *)texture->impl.texture3D, NULL, &texture->impl.view));
|
||||
}
|
||||
|
||||
void kinc_g4_texture_init(kinc_g4_texture_t *texture, int width, int height, kinc_image_format_t format) {
|
||||
memset(&texture->impl, 0, sizeof(texture->impl));
|
||||
texture->impl.stage = 0;
|
||||
texture->tex_width = width;
|
||||
texture->tex_height = height;
|
||||
texture->tex_depth = 1;
|
||||
texture->format = format;
|
||||
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
desc.Width = width;
|
||||
desc.Height = height;
|
||||
desc.MipLevels = desc.ArraySize = 1;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.MiscFlags = 0;
|
||||
|
||||
if (format == KINC_IMAGE_FORMAT_RGBA128) { // for compute
|
||||
desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
|
||||
desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.CPUAccessFlags = 0;
|
||||
}
|
||||
else {
|
||||
desc.Format = convertFormat(format);
|
||||
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
}
|
||||
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &desc, NULL, &texture->impl.texture));
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateShaderResourceView(dx_ctx.device, (ID3D11Resource *)texture->impl.texture, NULL, &texture->impl.view));
|
||||
|
||||
if (format == KINC_IMAGE_FORMAT_RGBA128) {
|
||||
D3D11_UNORDERED_ACCESS_VIEW_DESC du;
|
||||
du.Format = desc.Format;
|
||||
du.Texture2D.MipSlice = 0;
|
||||
du.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
|
||||
kinc_microsoft_affirm(
|
||||
dx_ctx.device->lpVtbl->CreateUnorderedAccessView(dx_ctx.device, (ID3D11Resource *)texture->impl.texture, &du, &texture->impl.computeView));
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_texture_init3d(kinc_g4_texture_t *texture, int width, int height, int depth, kinc_image_format_t format) {
|
||||
memset(&texture->impl, 0, sizeof(texture->impl));
|
||||
texture->impl.stage = 0;
|
||||
texture->tex_width = width;
|
||||
texture->tex_height = height;
|
||||
texture->tex_depth = depth;
|
||||
texture->format = format;
|
||||
texture->impl.hasMipmaps = true;
|
||||
|
||||
D3D11_TEXTURE3D_DESC desc;
|
||||
desc.Width = width;
|
||||
desc.Height = height;
|
||||
desc.Depth = depth;
|
||||
desc.MipLevels = 0;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;
|
||||
desc.Format = format == KINC_IMAGE_FORMAT_RGBA32 ? DXGI_FORMAT_R8G8B8A8_UNORM : DXGI_FORMAT_R8_UNORM;
|
||||
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET | D3D11_BIND_UNORDERED_ACCESS;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.CPUAccessFlags = 0;
|
||||
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture3D(dx_ctx.device, &desc, NULL, &texture->impl.texture3D));
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateShaderResourceView(dx_ctx.device, (ID3D11Resource *)texture->impl.texture3D, NULL, &texture->impl.view));
|
||||
}
|
||||
|
||||
// TextureImpl::TextureImpl() : hasMipmaps(false), renderView(nullptr), computeView(nullptr) {}
|
||||
|
||||
void kinc_internal_texture_unset(kinc_g4_texture_t *texture);
|
||||
|
||||
void kinc_g4_texture_destroy(kinc_g4_texture_t *texture) {
|
||||
kinc_internal_texture_unset(texture);
|
||||
if (texture->impl.view != NULL) {
|
||||
texture->impl.view->lpVtbl->Release(texture->impl.view);
|
||||
}
|
||||
if (texture->impl.texture != NULL) {
|
||||
texture->impl.texture->lpVtbl->Release(texture->impl.texture);
|
||||
}
|
||||
if (texture->impl.texture3D != NULL) {
|
||||
texture->impl.texture3D->lpVtbl->Release(texture->impl.texture3D);
|
||||
}
|
||||
if (texture->impl.computeView != NULL) {
|
||||
texture->impl.computeView->lpVtbl->Release(texture->impl.computeView);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_internal_texture_unmipmap(kinc_g4_texture_t *texture) {
|
||||
texture->impl.hasMipmaps = false;
|
||||
}
|
||||
|
||||
#ifdef KINC_KONG
|
||||
void kinc_internal_texture_set(kinc_g4_texture_t *texture, uint32_t unit) {
|
||||
dx_ctx.context->lpVtbl->PSSetShaderResources(dx_ctx.context, unit, 1, &texture->impl.view);
|
||||
|
||||
texture->impl.stage = unit;
|
||||
setTextures[unit] = texture;
|
||||
}
|
||||
#else
|
||||
void kinc_internal_texture_set(kinc_g4_texture_t *texture, kinc_g4_texture_unit_t unit) {
|
||||
if (unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] < 0 && unit.stages[KINC_G4_SHADER_TYPE_VERTEX] < 0)
|
||||
return;
|
||||
|
||||
if (unit.stages[KINC_G4_SHADER_TYPE_VERTEX] >= 0) {
|
||||
dx_ctx.context->lpVtbl->VSSetShaderResources(dx_ctx.context, unit.stages[KINC_G4_SHADER_TYPE_VERTEX], 1, &texture->impl.view);
|
||||
}
|
||||
|
||||
if (unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] >= 0) {
|
||||
dx_ctx.context->lpVtbl->PSSetShaderResources(dx_ctx.context, unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], 1, &texture->impl.view);
|
||||
}
|
||||
|
||||
texture->impl.stage = unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] >= 0 ? unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] : unit.stages[KINC_G4_SHADER_TYPE_VERTEX];
|
||||
setTextures[texture->impl.stage] = texture;
|
||||
}
|
||||
#endif
|
||||
|
||||
void kinc_internal_texture_set_image(kinc_g4_texture_t *texture, kinc_g4_texture_unit_t unit) {
|
||||
if (unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] < 0)
|
||||
return;
|
||||
|
||||
if (texture->impl.computeView == NULL) {
|
||||
D3D11_UNORDERED_ACCESS_VIEW_DESC du;
|
||||
du.Format = texture->format == KINC_IMAGE_FORMAT_RGBA32 ? DXGI_FORMAT_R8G8B8A8_UNORM : DXGI_FORMAT_R8_UNORM;
|
||||
du.Texture3D.MipSlice = 0;
|
||||
du.Texture3D.FirstWSlice = 0;
|
||||
du.Texture3D.WSize = -1;
|
||||
du.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D;
|
||||
kinc_microsoft_affirm(
|
||||
dx_ctx.device->lpVtbl->CreateUnorderedAccessView(dx_ctx.device, (ID3D11Resource *)texture->impl.texture3D, &du, &texture->impl.computeView));
|
||||
}
|
||||
dx_ctx.context->lpVtbl->OMSetRenderTargetsAndUnorderedAccessViews(dx_ctx.context, 0, NULL, NULL, unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], 1,
|
||||
&texture->impl.computeView, NULL);
|
||||
}
|
||||
|
||||
void kinc_internal_texture_unset(kinc_g4_texture_t *texture) {
|
||||
if (setTextures[texture->impl.stage] == texture) {
|
||||
|
||||
setTextures[texture->impl.stage] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *kinc_g4_texture_lock(kinc_g4_texture_t *texture) {
|
||||
D3D11_MAPPED_SUBRESOURCE mappedResource;
|
||||
kinc_microsoft_affirm(dx_ctx.context->lpVtbl->Map(dx_ctx.context, (ID3D11Resource *)texture->impl.texture, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource));
|
||||
texture->impl.rowPitch = mappedResource.RowPitch;
|
||||
return (uint8_t *)mappedResource.pData;
|
||||
}
|
||||
|
||||
void kinc_g4_texture_unlock(kinc_g4_texture_t *texture) {
|
||||
dx_ctx.context->lpVtbl->Unmap(dx_ctx.context, (ID3D11Resource *)texture->impl.texture, 0);
|
||||
}
|
||||
|
||||
void kinc_g4_texture_clear(kinc_g4_texture_t *texture, int x, int y, int z, int width, int height, int depth, unsigned color) {
|
||||
if (texture->impl.renderView == NULL) {
|
||||
texture->tex_depth > 1 ? kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateRenderTargetView(dx_ctx.device, (ID3D11Resource *)texture->impl.texture3D,
|
||||
0, &texture->impl.renderView))
|
||||
: kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateRenderTargetView(dx_ctx.device, (ID3D11Resource *)texture->impl.texture, 0,
|
||||
&texture->impl.renderView));
|
||||
}
|
||||
static float clearColor[4];
|
||||
clearColor[0] = ((color & 0x00ff0000) >> 16) / 255.0f;
|
||||
clearColor[1] = ((color & 0x0000ff00) >> 8) / 255.0f;
|
||||
clearColor[2] = (color & 0x000000ff) / 255.0f;
|
||||
clearColor[3] = ((color & 0xff000000) >> 24) / 255.0f;
|
||||
dx_ctx.context->lpVtbl->ClearRenderTargetView(dx_ctx.context, texture->impl.renderView, clearColor);
|
||||
}
|
||||
|
||||
int kinc_g4_texture_stride(kinc_g4_texture_t *texture) {
|
||||
assert(texture->impl.rowPitch != 0); // stride is not yet set, lock and unlock the texture first (or find a good fix for this and send a PR)
|
||||
return texture->impl.rowPitch;
|
||||
}
|
||||
|
||||
static void enableMipmaps(kinc_g4_texture_t *texture, int texWidth, int texHeight, int format) {
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
desc.Width = texWidth;
|
||||
desc.Height = texHeight;
|
||||
desc.MipLevels = 0;
|
||||
desc.ArraySize = 1;
|
||||
desc.Format = convertFormat((kinc_image_format_t)format);
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
|
||||
desc.CPUAccessFlags = 0;
|
||||
desc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;
|
||||
|
||||
ID3D11Texture2D *mipMappedTexture;
|
||||
ID3D11ShaderResourceView *mipMappedView;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &desc, NULL, &mipMappedTexture));
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateShaderResourceView(dx_ctx.device, (ID3D11Resource *)mipMappedTexture, NULL, &mipMappedView));
|
||||
|
||||
D3D11_BOX sourceRegion;
|
||||
sourceRegion.left = 0;
|
||||
sourceRegion.right = texWidth;
|
||||
sourceRegion.top = 0;
|
||||
sourceRegion.bottom = texHeight;
|
||||
sourceRegion.front = 0;
|
||||
sourceRegion.back = 1;
|
||||
dx_ctx.context->lpVtbl->CopySubresourceRegion(dx_ctx.context, (ID3D11Resource *)mipMappedTexture, 0, 0, 0, 0, (ID3D11Resource *)texture->impl.texture, 0,
|
||||
&sourceRegion);
|
||||
|
||||
if (texture->impl.texture != NULL) {
|
||||
texture->impl.texture->lpVtbl->Release(texture->impl.texture);
|
||||
}
|
||||
texture->impl.texture = mipMappedTexture;
|
||||
|
||||
if (texture->impl.view != NULL) {
|
||||
texture->impl.view->lpVtbl->Release(texture->impl.view);
|
||||
}
|
||||
texture->impl.view = mipMappedView;
|
||||
|
||||
texture->impl.hasMipmaps = true;
|
||||
}
|
||||
|
||||
void kinc_g4_texture_generate_mipmaps(kinc_g4_texture_t *texture, int levels) {
|
||||
if (!texture->impl.hasMipmaps) {
|
||||
enableMipmaps(texture, texture->tex_width, texture->tex_height, texture->format);
|
||||
}
|
||||
dx_ctx.context->lpVtbl->GenerateMips(dx_ctx.context, texture->impl.view);
|
||||
}
|
||||
|
||||
void kinc_g4_texture_set_mipmap(kinc_g4_texture_t *texture, kinc_image_t *mipmap, int level) {
|
||||
if (!texture->impl.hasMipmaps) {
|
||||
enableMipmaps(texture, texture->tex_width, texture->tex_height, texture->format);
|
||||
}
|
||||
D3D11_BOX dstRegion;
|
||||
dstRegion.left = 0;
|
||||
dstRegion.right = mipmap->width;
|
||||
dstRegion.top = 0;
|
||||
dstRegion.bottom = mipmap->height;
|
||||
dstRegion.front = 0;
|
||||
dstRegion.back = 1;
|
||||
dx_ctx.context->lpVtbl->UpdateSubresource(dx_ctx.context, (ID3D11Resource *)texture->impl.texture, level, &dstRegion, mipmap->data,
|
||||
mipmap->width * formatByteSize(mipmap->format), 0);
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
struct ID3D11Texture2D;
|
||||
struct ID3D11Texture3D;
|
||||
struct ID3D11ShaderResourceView;
|
||||
struct ID3D11UnorderedAccessView;
|
||||
struct ID3D11RenderTargetView;
|
||||
|
||||
// TextureImpl();
|
||||
//~TextureImpl();
|
||||
// void enableMipmaps(int texWidth, int texHeight, int format);
|
||||
// void unmipmap();
|
||||
// void unset();
|
||||
|
||||
typedef struct {
|
||||
bool hasMipmaps;
|
||||
int stage;
|
||||
struct ID3D11Texture2D *texture;
|
||||
struct ID3D11Texture3D *texture3D;
|
||||
struct ID3D11ShaderResourceView *view;
|
||||
struct ID3D11UnorderedAccessView *computeView;
|
||||
struct ID3D11RenderTargetView *renderView;
|
||||
int rowPitch;
|
||||
} kinc_g4_texture_impl_t;
|
@ -0,0 +1,39 @@
|
||||
#include <kinc/graphics4/texturearray.h>
|
||||
#include <kinc/graphics4/textureunit.h>
|
||||
|
||||
void kinc_g4_texture_array_init(kinc_g4_texture_array_t *array, kinc_image_t *textures, int count) {
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
desc.Width = textures[0].width;
|
||||
desc.Height = textures[0].height;
|
||||
desc.MipLevels = 1;
|
||||
desc.ArraySize = 2;
|
||||
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.CPUAccessFlags = 0;
|
||||
desc.MiscFlags = 0;
|
||||
|
||||
D3D11_SUBRESOURCE_DATA *resdata = (D3D11_SUBRESOURCE_DATA *)alloca(sizeof(D3D11_SUBRESOURCE_DATA) * count);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
resdata[i].pSysMem = textures[i].data;
|
||||
resdata[i].SysMemPitch = textures[0].width * 4;
|
||||
resdata[i].SysMemSlicePitch = 0;
|
||||
}
|
||||
|
||||
array->impl.texture = NULL;
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateTexture2D(dx_ctx.device, &desc, resdata, &array->impl.texture));
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateShaderResourceView(dx_ctx.device, (ID3D11Resource *)array->impl.texture, NULL, &array->impl.view));
|
||||
}
|
||||
|
||||
void kinc_g4_texture_array_destroy(kinc_g4_texture_array_t *array) {}
|
||||
|
||||
void kinc_internal_texture_array_set(kinc_g4_texture_array_t *array, kinc_g4_texture_unit_t unit) {
|
||||
if (unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] < 0)
|
||||
return;
|
||||
|
||||
dx_ctx.context->lpVtbl->PSSetShaderResources(dx_ctx.context, unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], 1, &array->impl.view);
|
||||
// this->stage = unit.unit;
|
||||
// setTextures[stage] = this;
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ID3D11Texture2D;
|
||||
struct ID3D11ShaderResourceView;
|
||||
|
||||
typedef struct {
|
||||
struct ID3D11Texture2D *texture;
|
||||
struct ID3D11ShaderResourceView *view;
|
||||
// void set(Kore::Graphics4::TextureUnit unit);
|
||||
} kinc_g4_texture_array_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,95 @@
|
||||
#include <kinc/graphics4/vertexbuffer.h>
|
||||
|
||||
void kinc_g4_vertex_buffer_init(kinc_g4_vertex_buffer_t *buffer, int count, kinc_g4_vertex_structure_t *structure, kinc_g4_usage_t usage,
|
||||
int instance_data_step_rate) {
|
||||
buffer->impl.count = count;
|
||||
buffer->impl.stride = 0;
|
||||
for (int i = 0; i < structure->size; ++i) {
|
||||
buffer->impl.stride += kinc_g4_vertex_data_size(structure->elements[i].data);
|
||||
}
|
||||
|
||||
if (usage == KINC_G4_USAGE_DYNAMIC) {
|
||||
buffer->impl.vertices = NULL;
|
||||
}
|
||||
else {
|
||||
buffer->impl.vertices = (float *)malloc(buffer->impl.stride * count);
|
||||
}
|
||||
|
||||
D3D11_BUFFER_DESC bufferDesc;
|
||||
bufferDesc.CPUAccessFlags = 0;
|
||||
|
||||
buffer->impl.usage = usage;
|
||||
switch (usage) {
|
||||
case KINC_G4_USAGE_STATIC:
|
||||
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
break;
|
||||
case KINC_G4_USAGE_DYNAMIC:
|
||||
bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
break;
|
||||
case KINC_G4_USAGE_READABLE:
|
||||
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
bufferDesc.ByteWidth = buffer->impl.stride * count;
|
||||
bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||
bufferDesc.MiscFlags = 0;
|
||||
bufferDesc.StructureByteStride = 0;
|
||||
|
||||
kinc_microsoft_affirm(dx_ctx.device->lpVtbl->CreateBuffer(dx_ctx.device, &bufferDesc, NULL, &buffer->impl.vb));
|
||||
}
|
||||
|
||||
void kinc_g4_vertex_buffer_destroy(kinc_g4_vertex_buffer_t *buffer) {
|
||||
buffer->impl.vb->lpVtbl->Release(buffer->impl.vb);
|
||||
free(buffer->impl.vertices);
|
||||
buffer->impl.vertices = NULL;
|
||||
}
|
||||
|
||||
float *kinc_g4_vertex_buffer_lock_all(kinc_g4_vertex_buffer_t *buffer) {
|
||||
return kinc_g4_vertex_buffer_lock(buffer, 0, buffer->impl.count);
|
||||
}
|
||||
|
||||
float *kinc_g4_vertex_buffer_lock(kinc_g4_vertex_buffer_t *buffer, int start, int count) {
|
||||
buffer->impl.lockStart = start;
|
||||
buffer->impl.lockCount = count;
|
||||
|
||||
if (buffer->impl.usage == KINC_G4_USAGE_DYNAMIC) {
|
||||
D3D11_MAPPED_SUBRESOURCE mappedResource;
|
||||
memset(&mappedResource, 0, sizeof(D3D11_MAPPED_SUBRESOURCE));
|
||||
dx_ctx.context->lpVtbl->Map(dx_ctx.context, (ID3D11Resource *)buffer->impl.vb, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
|
||||
float *data = (float *)mappedResource.pData;
|
||||
return &data[start * buffer->impl.stride / 4];
|
||||
}
|
||||
else {
|
||||
return &buffer->impl.vertices[start * buffer->impl.stride / 4];
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_vertex_buffer_unlock_all(kinc_g4_vertex_buffer_t *buffer) {
|
||||
kinc_g4_vertex_buffer_unlock(buffer, buffer->impl.lockCount);
|
||||
}
|
||||
|
||||
void kinc_g4_vertex_buffer_unlock(kinc_g4_vertex_buffer_t *buffer, int count) {
|
||||
if (buffer->impl.usage == KINC_G4_USAGE_DYNAMIC) {
|
||||
dx_ctx.context->lpVtbl->Unmap(dx_ctx.context, (ID3D11Resource *)buffer->impl.vb, 0);
|
||||
}
|
||||
else {
|
||||
dx_ctx.context->lpVtbl->UpdateSubresource(dx_ctx.context, (ID3D11Resource *)buffer->impl.vb, 0, NULL, buffer->impl.vertices, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
int kinc_internal_g4_vertex_buffer_set(kinc_g4_vertex_buffer_t *buffer, int offset) {
|
||||
// UINT stride = myStride;
|
||||
// UINT internaloffset = 0;
|
||||
// dx_ctx.context->IASetVertexBuffers(0, 1, &vb, &stride, &internaloffset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kinc_g4_vertex_buffer_count(kinc_g4_vertex_buffer_t *buffer) {
|
||||
return buffer->impl.count;
|
||||
}
|
||||
|
||||
int kinc_g4_vertex_buffer_stride(kinc_g4_vertex_buffer_t *buffer) {
|
||||
return buffer->impl.stride;
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
struct ID3D11Buffer;
|
||||
|
||||
typedef struct {
|
||||
struct ID3D11Buffer *vb;
|
||||
int stride;
|
||||
int count;
|
||||
int lockStart;
|
||||
int lockCount;
|
||||
float *vertices;
|
||||
int usage;
|
||||
} kinc_g4_vertex_buffer_impl_t;
|
@ -0,0 +1,66 @@
|
||||
#include <Kinc/Compute/Compute.h>
|
||||
#include <Kinc/Graphics4/RenderTarget.h>
|
||||
#include <Kinc/Graphics4/Texture.h>
|
||||
#include <Kinc/Math/Core.h>
|
||||
|
||||
void kinc_compute_shader_init(kinc_compute_shader_t *shader, void *source, int length) {}
|
||||
|
||||
void kinc_compute_shader_destroy(kinc_compute_shader_t *shader) {}
|
||||
|
||||
kinc_compute_constant_location_t kinc_compute_shader_get_constant_location(kinc_compute_shader_t *shader, const char *name) {
|
||||
kinc_compute_constant_location_t location = {0};
|
||||
return location;
|
||||
}
|
||||
|
||||
kinc_compute_texture_unit_t kinc_compute_shader_get_texture_unit(kinc_compute_shader_t *shader, const char *name) {
|
||||
kinc_compute_texture_unit_t unit = {0};
|
||||
return unit;
|
||||
}
|
||||
|
||||
void kinc_compute_set_bool(kinc_compute_constant_location_t location, bool value) {}
|
||||
|
||||
void kinc_compute_set_int(kinc_compute_constant_location_t location, int value) {}
|
||||
|
||||
void kinc_compute_set_float(kinc_compute_constant_location_t location, float value) {}
|
||||
|
||||
void kinc_compute_set_float2(kinc_compute_constant_location_t location, float value1, float value2) {}
|
||||
|
||||
void kinc_compute_set_float3(kinc_compute_constant_location_t location, float value1, float value2, float value3) {}
|
||||
|
||||
void kinc_compute_set_float4(kinc_compute_constant_location_t location, float value1, float value2, float value3, float value4) {}
|
||||
|
||||
void kinc_compute_set_floats(kinc_compute_constant_location_t location, float *values, int count) {}
|
||||
|
||||
void kinc_compute_set_matrix4(kinc_compute_constant_location_t location, kinc_matrix4x4_t *value) {}
|
||||
|
||||
void kinc_compute_set_matrix3(kinc_compute_constant_location_t location, kinc_matrix3x3_t *value) {}
|
||||
|
||||
void kinc_compute_set_texture(kinc_compute_texture_unit_t unit, kinc_g4_texture_t *texture, kinc_compute_access_t access) {}
|
||||
|
||||
void kinc_compute_set_render_target(kinc_compute_texture_unit_t unit, kinc_g4_render_target_t *target, kinc_compute_access_t access) {}
|
||||
|
||||
void kinc_compute_set_sampled_texture(kinc_compute_texture_unit_t unit, kinc_g4_texture_t *texture) {}
|
||||
|
||||
void kinc_compute_set_sampled_render_target(kinc_compute_texture_unit_t unit, kinc_g4_render_target_t *target) {}
|
||||
|
||||
void kinc_compute_set_sampled_depth_from_render_target(kinc_compute_texture_unit_t unit, kinc_g4_render_target_t *target) {}
|
||||
|
||||
void kinc_compute_set_texture_addressing(kinc_compute_texture_unit_t unit, kinc_g4_texture_direction_t dir, kinc_g4_texture_addressing_t addressing) {}
|
||||
|
||||
void kinc_compute_set_texture3d_addressing(kinc_compute_texture_unit_t unit, kinc_g4_texture_direction_t dir, kinc_g4_texture_addressing_t addressing) {}
|
||||
|
||||
void kinc_compute_set_texture_magnification_filter(kinc_compute_texture_unit_t unit, kinc_g4_texture_filter_t filter) {}
|
||||
|
||||
void kinc_compute_set_texture3d_magnification_filter(kinc_compute_texture_unit_t unit, kinc_g4_texture_filter_t filter) {}
|
||||
|
||||
void kinc_compute_set_texture_minification_filter(kinc_compute_texture_unit_t unit, kinc_g4_texture_filter_t filter) {}
|
||||
|
||||
void kinc_compute_set_texture3d_minification_filter(kinc_compute_texture_unit_t unit, kinc_g4_texture_filter_t filter) {}
|
||||
|
||||
void kinc_compute_set_texture_mipmap_filter(kinc_compute_texture_unit_t unit, kinc_g4_mipmap_filter_t filter) {}
|
||||
|
||||
void kinc_compute_set_texture3d_mipmap_filter(kinc_compute_texture_unit_t unit, kinc_g4_mipmap_filter_t filter) {}
|
||||
|
||||
void kinc_compute_set_shader(kinc_compute_shader_t *shader) {}
|
||||
|
||||
void kinc_compute(int x, int y, int z) {}
|
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
int nothing;
|
||||
} kinc_compute_constant_location_impl_t;
|
||||
|
||||
typedef struct {
|
||||
int nothing;
|
||||
} kinc_compute_texture_unit_impl_t;
|
||||
|
||||
typedef struct {
|
||||
int nothing;
|
||||
} kinc_compute_internal_shader_constant_t;
|
||||
|
||||
typedef struct {
|
||||
int nothing;
|
||||
} kinc_compute_shader_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,841 @@
|
||||
#include <kinc/display.h>
|
||||
#include <kinc/graphics4/graphics.h>
|
||||
#include <kinc/graphics4/indexbuffer.h>
|
||||
#include <kinc/graphics4/pipeline.h>
|
||||
#include <kinc/graphics4/shader.h>
|
||||
#include <kinc/graphics4/texture.h>
|
||||
#include <kinc/graphics4/vertexbuffer.h>
|
||||
#include <kinc/math/core.h>
|
||||
|
||||
#undef CreateWindow
|
||||
#include <kinc/system.h>
|
||||
#include <kinc/window.h>
|
||||
|
||||
#include <kinc/backend/SystemMicrosoft.h>
|
||||
#include <kinc/backend/Windows.h>
|
||||
|
||||
#include <kinc/log.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "Direct3D9.h"
|
||||
|
||||
LPDIRECT3D9 d3d;
|
||||
LPDIRECT3DDEVICE9 device;
|
||||
|
||||
namespace {
|
||||
HWND hWnd;
|
||||
|
||||
int _width;
|
||||
int _height;
|
||||
|
||||
unsigned hz;
|
||||
bool vsync;
|
||||
|
||||
bool resizable;
|
||||
|
||||
D3DVIEWPORT9 vp;
|
||||
|
||||
bool swapBuffers() {
|
||||
HRESULT result;
|
||||
if (resizable) {
|
||||
RECT vRect;
|
||||
GetClientRect(hWnd, &vRect);
|
||||
result = device->Present(&vRect, &vRect, 0, 0);
|
||||
}
|
||||
else {
|
||||
result = device->Present(0, 0, 0, 0);
|
||||
}
|
||||
return result != D3DERR_DEVICELOST;
|
||||
}
|
||||
|
||||
kinc_g4_shader_t *pixelShader = nullptr;
|
||||
kinc_g4_shader_t *vertexShader = nullptr;
|
||||
IDirect3DSurface9 *backBuffer = nullptr;
|
||||
IDirect3DSurface9 *depthBuffer = nullptr;
|
||||
|
||||
void initDeviceStates() {
|
||||
D3DCAPS9 caps;
|
||||
device->GetDeviceCaps(&caps);
|
||||
|
||||
device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
|
||||
// device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
|
||||
#ifndef USE_SHADER
|
||||
device->SetRenderState(D3DRS_LIGHTING, FALSE);
|
||||
#endif
|
||||
device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
|
||||
device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
||||
device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
||||
|
||||
#ifndef USE_SHADER
|
||||
device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
||||
device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
||||
device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT);
|
||||
kinc_microsoft_affirm(device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE));
|
||||
kinc_microsoft_affirm(device->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE));
|
||||
#endif
|
||||
// if (d3dpp.Windowed != TRUE) Cursor->Hide();
|
||||
|
||||
device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
|
||||
device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
device->SetSamplerState(i, D3DSAMP_MAGFILTER, D3DTEXF_ANISOTROPIC);
|
||||
device->SetSamplerState(i, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC);
|
||||
device->SetSamplerState(i, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
|
||||
device->SetSamplerState(i, D3DSAMP_MAXANISOTROPY, caps.MaxAnisotropy);
|
||||
}
|
||||
|
||||
device->SetSamplerState(D3DVERTEXTEXTURESAMPLER0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
||||
device->SetSamplerState(D3DVERTEXTEXTURESAMPLER0, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC);
|
||||
|
||||
device->SetRenderState(D3DRS_ZENABLE, FALSE);
|
||||
|
||||
device->Clear(0, 0, D3DCLEAR_TARGET, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_internal_destroy_window(int window) {}
|
||||
void kinc_g4_internal_destroy() {}
|
||||
|
||||
extern "C" void kinc_internal_resize(int width, int height) {
|
||||
if (!resizable) {
|
||||
return;
|
||||
}
|
||||
|
||||
_width = width;
|
||||
_height = height;
|
||||
kinc_g4_viewport(0, 0, width, height);
|
||||
/*D3DPRESENT_PARAMETERS d3dpp;
|
||||
ZeroMemory(&d3dpp, sizeof(d3dpp));
|
||||
d3dpp.Windowed = (!fullscreen) ? TRUE : FALSE;
|
||||
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
||||
d3dpp.BackBufferCount = 2;
|
||||
d3dpp.BackBufferWidth = width;
|
||||
d3dpp.BackBufferHeight = height;
|
||||
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
|
||||
d3dpp.EnableAutoDepthStencil = TRUE;
|
||||
d3dpp.AutoDepthStencilFormat = D3DFMT_D24X8;
|
||||
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE; //D3DPRESENT_INTERVAL_IMMEDIATE;
|
||||
if (antialiasing()) {
|
||||
if (SUCCEEDED(d3d->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_A8R8G8B8, FALSE, D3DMULTISAMPLE_4_SAMPLES, nullptr)))
|
||||
d3dpp.MultiSampleType = D3DMULTISAMPLE_4_SAMPLES;
|
||||
if (SUCCEEDED(d3d->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_A8R8G8B8, FALSE, D3DMULTISAMPLE_8_SAMPLES, nullptr)))
|
||||
d3dpp.MultiSampleType = D3DMULTISAMPLE_8_SAMPLES;
|
||||
}
|
||||
else {
|
||||
d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
|
||||
}
|
||||
|
||||
device->Reset(&d3dpp);
|
||||
|
||||
initDeviceStates();*/
|
||||
}
|
||||
|
||||
extern "C" void kinc_internal_change_framebuffer(int window, struct kinc_framebuffer_options *frame) {}
|
||||
|
||||
void kinc_g4_internal_init() {}
|
||||
|
||||
void kinc_g4_internal_init_window(int windowId, int depthBufferBits, int stencilBufferBits, bool vsync) {
|
||||
bool fullscreen = kinc_window_get_mode(windowId) == KINC_WINDOW_MODE_FULLSCREEN || kinc_window_get_mode(windowId) == KINC_WINDOW_MODE_EXCLUSIVE_FULLSCREEN;
|
||||
|
||||
d3d = Direct3DCreate9(D3D_SDK_VERSION);
|
||||
|
||||
hWnd = kinc_windows_window_handle(windowId);
|
||||
long style = GetWindowLong(hWnd, GWL_STYLE);
|
||||
|
||||
resizable = false;
|
||||
|
||||
if ((style & WS_SIZEBOX) != 0) {
|
||||
resizable = true;
|
||||
}
|
||||
|
||||
if ((style & WS_MAXIMIZEBOX) != 0) {
|
||||
resizable = true;
|
||||
}
|
||||
|
||||
// TODO (DK) just setup the primary window for now and ignore secondaries
|
||||
// -this should probably be implemented via swap chain for real at a later time
|
||||
// -http://www.mvps.org/directx/articles/rendering_to_multiple_windows.htm
|
||||
if (windowId > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef KORE_WINDOWS
|
||||
// TODO (DK) convert depthBufferBits + stencilBufferBits to: d3dpp.AutoDepthStencilFormat = D3DFMT_D24X8;
|
||||
D3DPRESENT_PARAMETERS d3dpp;
|
||||
ZeroMemory(&d3dpp, sizeof(d3dpp));
|
||||
d3dpp.Windowed = (!fullscreen) ? TRUE : FALSE;
|
||||
|
||||
if (resizable) {
|
||||
d3dpp.SwapEffect = D3DSWAPEFFECT_COPY;
|
||||
d3dpp.BackBufferCount = 1;
|
||||
kinc_display_mode_t mode = kinc_display_current_mode(kinc_primary_display());
|
||||
d3dpp.BackBufferWidth = mode.width;
|
||||
d3dpp.BackBufferHeight = mode.height;
|
||||
}
|
||||
else {
|
||||
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
||||
d3dpp.BackBufferCount = 2;
|
||||
d3dpp.BackBufferWidth = kinc_window_width(windowId);
|
||||
d3dpp.BackBufferHeight = kinc_window_height(windowId);
|
||||
}
|
||||
|
||||
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
|
||||
d3dpp.EnableAutoDepthStencil = TRUE;
|
||||
d3dpp.AutoDepthStencilFormat = D3DFMT_D24X8;
|
||||
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
|
||||
// d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
|
||||
d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
|
||||
if (kinc_g4_antialiasing_samples() > 1) {
|
||||
for (int samples = min(kinc_g4_antialiasing_samples(), 16); samples > 1; --samples) {
|
||||
if (SUCCEEDED(d3d->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_A8R8G8B8, FALSE, (D3DMULTISAMPLE_TYPE)samples, nullptr))) {
|
||||
d3dpp.MultiSampleType = (D3DMULTISAMPLE_TYPE)samples;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!SUCCEEDED(d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &device)))
|
||||
d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device);
|
||||
// d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device);
|
||||
|
||||
#ifdef KORE_WINDOWS
|
||||
// if (System::hasShowWindowFlag(/*windowId*/)) {
|
||||
ShowWindow(hWnd, SW_SHOWDEFAULT);
|
||||
UpdateWindow(hWnd);
|
||||
//}
|
||||
#endif
|
||||
|
||||
initDeviceStates();
|
||||
|
||||
#ifdef KORE_WINDOWS
|
||||
if (fullscreen) {
|
||||
// hz = d3dpp.FullScreen_RefreshRateInHz;
|
||||
D3DDISPLAYMODE mode;
|
||||
device->GetDisplayMode(0, &mode);
|
||||
hz = mode.RefreshRate;
|
||||
}
|
||||
if (!fullscreen || hz == 0) {
|
||||
DEVMODE devMode;
|
||||
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devMode);
|
||||
hz = devMode.dmDisplayFrequency;
|
||||
}
|
||||
#endif
|
||||
|
||||
// vsync = d3dpp.PresentationInterval != D3DPRESENT_INTERVAL_IMMEDIATE;
|
||||
|
||||
kinc_ticks_t test1 = kinc_timestamp();
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
kinc_g4_swap_buffers();
|
||||
}
|
||||
kinc_ticks_t test2 = kinc_timestamp();
|
||||
if (test2 - test1 < (1.0 / hz) * kinc_frequency()) {
|
||||
vsync = false;
|
||||
}
|
||||
else {
|
||||
vsync = true;
|
||||
}
|
||||
|
||||
_width = kinc_window_width(windowId);
|
||||
_height = kinc_window_height(windowId);
|
||||
}
|
||||
|
||||
void kinc_g4_flush() {}
|
||||
|
||||
namespace {
|
||||
DWORD convertFilter(kinc_g4_texture_filter_t filter) {
|
||||
switch (filter) {
|
||||
case KINC_G4_TEXTURE_FILTER_POINT:
|
||||
return D3DTEXF_POINT;
|
||||
case KINC_G4_TEXTURE_FILTER_LINEAR:
|
||||
return D3DTEXF_LINEAR;
|
||||
case KINC_G4_TEXTURE_FILTER_ANISOTROPIC:
|
||||
return D3DTEXF_ANISOTROPIC;
|
||||
default:
|
||||
return D3DTEXF_POINT;
|
||||
}
|
||||
}
|
||||
|
||||
DWORD convertMipFilter(kinc_g4_mipmap_filter_t filter) {
|
||||
switch (filter) {
|
||||
case KINC_G4_MIPMAP_FILTER_NONE:
|
||||
return D3DTEXF_NONE;
|
||||
case KINC_G4_MIPMAP_FILTER_POINT:
|
||||
return D3DTEXF_POINT;
|
||||
case KINC_G4_MIPMAP_FILTER_LINEAR:
|
||||
return D3DTEXF_LINEAR;
|
||||
default:
|
||||
return D3DTEXF_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture_magnification_filter(kinc_g4_texture_unit_t texunit, kinc_g4_texture_filter_t filter) {
|
||||
device->SetSamplerState(texunit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], D3DSAMP_MAGFILTER, convertFilter(filter));
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture3d_magnification_filter(kinc_g4_texture_unit_t texunit, kinc_g4_texture_filter_t filter) {
|
||||
kinc_g4_set_texture_magnification_filter(texunit, filter);
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture_minification_filter(kinc_g4_texture_unit_t texunit, kinc_g4_texture_filter_t filter) {
|
||||
device->SetSamplerState(texunit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], D3DSAMP_MINFILTER, convertFilter(filter));
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture3d_minification_filter(kinc_g4_texture_unit_t texunit, kinc_g4_texture_filter_t filter) {
|
||||
kinc_g4_set_texture_minification_filter(texunit, filter);
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture_mipmap_filter(kinc_g4_texture_unit_t texunit, kinc_g4_mipmap_filter_t filter) {
|
||||
device->SetSamplerState(texunit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], D3DSAMP_MIPFILTER, convertMipFilter(filter));
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture3d_mipmap_filter(kinc_g4_texture_unit_t texunit, kinc_g4_mipmap_filter_t filter) {
|
||||
kinc_g4_set_texture_mipmap_filter(texunit, filter);
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture_compare_mode(kinc_g4_texture_unit_t unit, bool enabled) {}
|
||||
|
||||
void kinc_g4_set_texture_compare_func(kinc_g4_texture_unit_t unit, kinc_g4_compare_mode_t mode) {}
|
||||
|
||||
void kinc_g4_set_cubemap_compare_mode(kinc_g4_texture_unit_t unit, bool enabled) {}
|
||||
|
||||
void kinc_g4_set_cubemap_compare_func(kinc_g4_texture_unit_t unit, kinc_g4_compare_mode_t mode) {}
|
||||
|
||||
void kinc_g4_set_texture_max_anisotropy(kinc_g4_texture_unit_t unit, uint16_t max_anisotropy) {
|
||||
device->SetSamplerState(unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], D3DSAMP_MAXANISOTROPY, max_anisotropy);
|
||||
}
|
||||
|
||||
void kinc_g4_set_cubemap_max_anisotropy(kinc_g4_texture_unit_t unit, uint16_t max_anisotropy) {}
|
||||
|
||||
void kinc_g4_set_texture_lod(kinc_g4_texture_unit_t unit, float lod_min_clamp, float lod_max_clamp) {
|
||||
// device->SetSamplerState(unit.impl.unit, D3DSAMP_, );
|
||||
}
|
||||
|
||||
void kinc_g4_set_cubemap_lod(kinc_g4_texture_unit_t unit, float lod_min_clamp, float lod_max_clamp) {}
|
||||
|
||||
void kinc_g4_set_render_targets(struct kinc_g4_render_target **targets, int count) {
|
||||
// if (backBuffer != nullptr) backBuffer->Release();
|
||||
|
||||
if (backBuffer == nullptr) {
|
||||
device->GetRenderTarget(0, &backBuffer);
|
||||
device->GetDepthStencilSurface(&depthBuffer);
|
||||
}
|
||||
kinc_microsoft_affirm(device->SetDepthStencilSurface(targets[0]->impl.depthSurface));
|
||||
for (int i = 0; i < count; ++i) {
|
||||
kinc_microsoft_affirm(device->SetRenderTarget(i, targets[i]->impl.colorSurface));
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_set_render_target_face(struct kinc_g4_render_target *texture, int face) {}
|
||||
|
||||
int kinc_g4_max_bound_textures(void) {
|
||||
return 8;
|
||||
}
|
||||
|
||||
// void Graphics::setDepthStencilTarget(Texture* texture) {
|
||||
// //if (depthBuffer != nullptr) depthBuffer->Release();
|
||||
// device->GetDepthStencilSurface(&depthBuffer);
|
||||
// Microsoft::affirm(device->SetDepthStencilSurface(dcast<D3D9Texture*>(texture)->getSurface()));
|
||||
//}
|
||||
|
||||
void kinc_g4_restore_render_target() {
|
||||
if (backBuffer != nullptr) {
|
||||
device->SetRenderTarget(0, backBuffer);
|
||||
device->SetRenderTarget(1, nullptr);
|
||||
backBuffer->Release();
|
||||
backBuffer = nullptr;
|
||||
device->SetDepthStencilSurface(depthBuffer);
|
||||
depthBuffer->Release();
|
||||
depthBuffer = nullptr;
|
||||
kinc_g4_viewport(0, 0, _width, _height);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_draw_indexed_vertices() {
|
||||
device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, kinc_g4_vertex_buffer_count(kinc_internal_current_vertex_buffer), 0,
|
||||
kinc_g4_index_buffer_count(kinc_internal_current_index_buffer) / 3);
|
||||
}
|
||||
|
||||
void kinc_g4_draw_indexed_vertices_from_to(int start, int count) {
|
||||
device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, kinc_g4_vertex_buffer_count(kinc_internal_current_vertex_buffer), start, count / 3);
|
||||
}
|
||||
|
||||
void kinc_g4_draw_indexed_vertices_from_to_from(int start, int count, int vertex_offset) {
|
||||
device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, vertex_offset, 0, kinc_g4_vertex_buffer_count(kinc_internal_current_vertex_buffer), start, count / 3);
|
||||
}
|
||||
|
||||
void kinc_g4_draw_indexed_vertices_instanced(int instanceCount) {
|
||||
kinc_microsoft_affirm(device->SetStreamSourceFreq(kinc_internal_current_vertex_buffer->impl._offset, (D3DSTREAMSOURCE_INDEXEDDATA | instanceCount)));
|
||||
device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, kinc_g4_vertex_buffer_count(kinc_internal_current_vertex_buffer), 0,
|
||||
kinc_g4_index_buffer_count(kinc_internal_current_index_buffer) / 3);
|
||||
}
|
||||
|
||||
void kinc_g4_draw_indexed_vertices_instanced_from_to(int instanceCount, int start, int count) {
|
||||
kinc_microsoft_affirm(device->SetStreamSourceFreq(kinc_internal_current_vertex_buffer->impl._offset, (D3DSTREAMSOURCE_INDEXEDDATA | instanceCount)));
|
||||
device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, kinc_g4_vertex_buffer_count(kinc_internal_current_vertex_buffer), start, count / 3);
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture_addressing(kinc_g4_texture_unit_t unit, kinc_g4_texture_direction_t dir, kinc_g4_texture_addressing_t addressing) {
|
||||
DWORD value = 0;
|
||||
switch (addressing) {
|
||||
case KINC_G4_TEXTURE_ADDRESSING_REPEAT:
|
||||
value = D3DTADDRESS_WRAP;
|
||||
break;
|
||||
case KINC_G4_TEXTURE_ADDRESSING_MIRROR:
|
||||
value = D3DTADDRESS_MIRROR;
|
||||
break;
|
||||
case KINC_G4_TEXTURE_ADDRESSING_CLAMP:
|
||||
value = D3DTADDRESS_CLAMP;
|
||||
break;
|
||||
case KINC_G4_TEXTURE_ADDRESSING_BORDER:
|
||||
value = D3DTADDRESS_BORDER;
|
||||
break;
|
||||
}
|
||||
device->SetSamplerState(unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], dir == KINC_G4_TEXTURE_DIRECTION_U ? D3DSAMP_ADDRESSU : D3DSAMP_ADDRESSV, value);
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture3d_addressing(kinc_g4_texture_unit_t unit, kinc_g4_texture_direction_t dir, kinc_g4_texture_addressing_t addressing) {
|
||||
kinc_g4_set_texture_addressing(unit, dir, addressing);
|
||||
}
|
||||
|
||||
namespace {
|
||||
void tod3dmatrix(kinc_matrix4x4_t *matrix, D3DMATRIX &d3dm) {
|
||||
d3dm._11 = kinc_matrix4x4_get(matrix, 0, 0);
|
||||
d3dm._12 = kinc_matrix4x4_get(matrix, 0, 1);
|
||||
d3dm._13 = kinc_matrix4x4_get(matrix, 0, 2);
|
||||
d3dm._14 = kinc_matrix4x4_get(matrix, 0, 3);
|
||||
|
||||
d3dm._21 = kinc_matrix4x4_get(matrix, 1, 0);
|
||||
d3dm._22 = kinc_matrix4x4_get(matrix, 1, 1);
|
||||
d3dm._23 = kinc_matrix4x4_get(matrix, 1, 2);
|
||||
d3dm._24 = kinc_matrix4x4_get(matrix, 1, 3);
|
||||
|
||||
d3dm._31 = kinc_matrix4x4_get(matrix, 2, 0);
|
||||
d3dm._32 = kinc_matrix4x4_get(matrix, 2, 1);
|
||||
d3dm._33 = kinc_matrix4x4_get(matrix, 2, 2);
|
||||
d3dm._34 = kinc_matrix4x4_get(matrix, 2, 3);
|
||||
|
||||
d3dm._41 = kinc_matrix4x4_get(matrix, 3, 0);
|
||||
d3dm._42 = kinc_matrix4x4_get(matrix, 3, 1);
|
||||
d3dm._43 = kinc_matrix4x4_get(matrix, 3, 2);
|
||||
d3dm._44 = kinc_matrix4x4_get(matrix, 3, 3);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_clear(unsigned flags, unsigned color, float depth, int stencil) {
|
||||
device->Clear(0, nullptr, flags, color, depth, stencil);
|
||||
}
|
||||
|
||||
void kinc_g4_begin(int window) {
|
||||
// TODO (DK) ignore secondary windows for now
|
||||
if (window > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
kinc_g4_viewport(0, 0, _width, _height);
|
||||
device->BeginScene();
|
||||
}
|
||||
|
||||
void kinc_g4_viewport(int x, int y, int width, int height) {
|
||||
vp.X = x;
|
||||
vp.Y = y;
|
||||
vp.Width = width;
|
||||
vp.Height = height;
|
||||
device->SetViewport(&vp);
|
||||
}
|
||||
|
||||
void kinc_g4_scissor(int x, int y, int width, int height) {
|
||||
device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
|
||||
|
||||
RECT rc;
|
||||
rc.left = x;
|
||||
rc.top = y;
|
||||
rc.right = x + width;
|
||||
rc.bottom = y + height;
|
||||
device->SetScissorRect(&rc);
|
||||
}
|
||||
|
||||
void kinc_g4_disable_scissor() {
|
||||
device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
|
||||
}
|
||||
|
||||
void kinc_g4_end(int window) {
|
||||
// TODO (DK) ignore secondary windows for now
|
||||
if (window > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*if (backBuffer != nullptr) {
|
||||
backBuffer->Release();
|
||||
backBuffer = nullptr;
|
||||
}*/
|
||||
device->EndScene();
|
||||
}
|
||||
|
||||
bool kinc_window_vsynced(int window) {
|
||||
return vsync;
|
||||
}
|
||||
|
||||
// unsigned Graphics4::refreshRate() {
|
||||
// return hz;
|
||||
//}
|
||||
|
||||
bool kinc_g4_swap_buffers() {
|
||||
return ::swapBuffers();
|
||||
}
|
||||
|
||||
void kinc_g4_set_stencil_reference_value(int value) {}
|
||||
|
||||
void kinc_g4_set_blend_constant(float r, float g, float b, float a) {
|
||||
device->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA((int)(r * 255), (int)(g * 255), (int)(b * 255), (int)(a * 255)));
|
||||
}
|
||||
|
||||
void kinc_g4_set_bool(kinc_g4_constant_location_t position, bool value) {
|
||||
if (position.impl.shaderType == -1)
|
||||
return;
|
||||
BOOL bools[4];
|
||||
bools[0] = value ? 1 : 0;
|
||||
bools[1] = bools[0];
|
||||
bools[2] = bools[0];
|
||||
bools[3] = bools[0];
|
||||
if (position.impl.shaderType == 0)
|
||||
device->SetVertexShaderConstantB(position.impl.reg.regindex, &bools[0], 1);
|
||||
else
|
||||
device->SetPixelShaderConstantB(position.impl.reg.regindex, &bools[0], 1);
|
||||
}
|
||||
|
||||
void kinc_g4_set_int(kinc_g4_constant_location_t position, int value) {
|
||||
if (position.impl.shaderType == -1)
|
||||
return;
|
||||
if (position.impl.reg.regtype == 'f') {
|
||||
kinc_g4_set_float(position, (float)value);
|
||||
}
|
||||
else {
|
||||
int ints[4];
|
||||
ints[0] = value;
|
||||
ints[1] = value;
|
||||
ints[2] = value;
|
||||
ints[3] = value;
|
||||
if (position.impl.shaderType == 0)
|
||||
device->SetVertexShaderConstantI(position.impl.reg.regindex, &ints[0], 1);
|
||||
else
|
||||
device->SetPixelShaderConstantI(position.impl.reg.regindex, &ints[0], 1);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_set_int2(kinc_g4_constant_location_t position, int value1, int value2) {
|
||||
if (position.impl.shaderType == -1)
|
||||
return;
|
||||
if (position.impl.reg.regtype == 'f') {
|
||||
kinc_g4_set_float2(position, (float)value1, (float)value2);
|
||||
}
|
||||
else {
|
||||
int ints[4];
|
||||
ints[0] = value1;
|
||||
ints[1] = value2;
|
||||
ints[2] = value1;
|
||||
ints[3] = value2;
|
||||
if (position.impl.shaderType == 0)
|
||||
device->SetVertexShaderConstantI(position.impl.reg.regindex, &ints[0], 1);
|
||||
else
|
||||
device->SetPixelShaderConstantI(position.impl.reg.regindex, &ints[0], 1);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_set_int3(kinc_g4_constant_location_t position, int value1, int value2, int value3) {
|
||||
if (position.impl.shaderType == -1)
|
||||
return;
|
||||
if (position.impl.reg.regtype == 'f') {
|
||||
kinc_g4_set_float3(position, (float)value1, (float)value2, (float)value3);
|
||||
}
|
||||
else {
|
||||
int ints[4];
|
||||
ints[0] = value1;
|
||||
ints[1] = value2;
|
||||
ints[2] = value3;
|
||||
ints[3] = value1;
|
||||
if (position.impl.shaderType == 0)
|
||||
device->SetVertexShaderConstantI(position.impl.reg.regindex, &ints[0], 1);
|
||||
else
|
||||
device->SetPixelShaderConstantI(position.impl.reg.regindex, &ints[0], 1);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_set_int4(kinc_g4_constant_location_t position, int value1, int value2, int value3, int value4) {
|
||||
if (position.impl.shaderType == -1)
|
||||
return;
|
||||
if (position.impl.reg.regtype == 'f') {
|
||||
kinc_g4_set_float4(position, (float)value1, (float)value2, (float)value3, (float)value4);
|
||||
}
|
||||
else {
|
||||
int ints[4];
|
||||
ints[0] = value1;
|
||||
ints[1] = value2;
|
||||
ints[2] = value3;
|
||||
ints[3] = value4;
|
||||
if (position.impl.shaderType == 0)
|
||||
device->SetVertexShaderConstantI(position.impl.reg.regindex, &ints[0], 1);
|
||||
else
|
||||
device->SetPixelShaderConstantI(position.impl.reg.regindex, &ints[0], 1);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_set_ints(kinc_g4_constant_location_t location, int *values, int count) {
|
||||
if (location.impl.shaderType == -1)
|
||||
return;
|
||||
int registerCount = (count + 3) / 4; // round up
|
||||
if (registerCount == count / 4) { // round down
|
||||
if (location.impl.shaderType == 0)
|
||||
device->SetVertexShaderConstantI(location.impl.reg.regindex, values, registerCount);
|
||||
else
|
||||
device->SetPixelShaderConstantI(location.impl.reg.regindex, values, registerCount);
|
||||
}
|
||||
else {
|
||||
int *data = (int *)alloca(registerCount * 4 * sizeof(int));
|
||||
memcpy(data, values, count * sizeof(int));
|
||||
if (location.impl.shaderType == 0)
|
||||
device->SetVertexShaderConstantI(location.impl.reg.regindex, data, registerCount);
|
||||
else
|
||||
device->SetPixelShaderConstantI(location.impl.reg.regindex, data, registerCount);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_set_float(kinc_g4_constant_location_t position, float value) {
|
||||
if (position.impl.shaderType == -1)
|
||||
return;
|
||||
float floats[4];
|
||||
floats[0] = value;
|
||||
floats[1] = value;
|
||||
floats[2] = value;
|
||||
floats[3] = value;
|
||||
if (position.impl.shaderType == 0)
|
||||
device->SetVertexShaderConstantF(position.impl.reg.regindex, floats, 1);
|
||||
else
|
||||
device->SetPixelShaderConstantF(position.impl.reg.regindex, floats, 1);
|
||||
}
|
||||
|
||||
void kinc_g4_set_float2(kinc_g4_constant_location_t position, float value1, float value2) {
|
||||
if (position.impl.shaderType == -1)
|
||||
return;
|
||||
float floats[4];
|
||||
floats[0] = value1;
|
||||
floats[1] = value2;
|
||||
floats[2] = value1;
|
||||
floats[3] = value2;
|
||||
if (position.impl.shaderType == 0)
|
||||
device->SetVertexShaderConstantF(position.impl.reg.regindex, floats, 1);
|
||||
else
|
||||
device->SetPixelShaderConstantF(position.impl.reg.regindex, floats, 1);
|
||||
}
|
||||
|
||||
void kinc_g4_set_float3(kinc_g4_constant_location_t position, float value1, float value2, float value3) {
|
||||
if (position.impl.shaderType == -1)
|
||||
return;
|
||||
float floats[4];
|
||||
floats[0] = value1;
|
||||
floats[1] = value2;
|
||||
floats[2] = value3;
|
||||
floats[3] = value1;
|
||||
if (position.impl.shaderType == 0)
|
||||
device->SetVertexShaderConstantF(position.impl.reg.regindex, floats, 1);
|
||||
else
|
||||
device->SetPixelShaderConstantF(position.impl.reg.regindex, floats, 1);
|
||||
}
|
||||
|
||||
void kinc_g4_set_float4(kinc_g4_constant_location_t position, float value1, float value2, float value3, float value4) {
|
||||
if (position.impl.shaderType == -1)
|
||||
return;
|
||||
float floats[4];
|
||||
floats[0] = value1;
|
||||
floats[1] = value2;
|
||||
floats[2] = value3;
|
||||
floats[3] = value4;
|
||||
if (position.impl.shaderType == 0)
|
||||
device->SetVertexShaderConstantF(position.impl.reg.regindex, floats, 1);
|
||||
else
|
||||
device->SetPixelShaderConstantF(position.impl.reg.regindex, floats, 1);
|
||||
}
|
||||
|
||||
void kinc_g4_set_floats(kinc_g4_constant_location_t location, float *values, int count) {
|
||||
if (location.impl.shaderType == -1)
|
||||
return;
|
||||
int registerCount = (count + 3) / 4; // round up
|
||||
if (registerCount == count / 4) { // round down
|
||||
if (location.impl.shaderType == 0)
|
||||
device->SetVertexShaderConstantF(location.impl.reg.regindex, values, registerCount);
|
||||
else
|
||||
device->SetPixelShaderConstantF(location.impl.reg.regindex, values, registerCount);
|
||||
}
|
||||
else {
|
||||
float *data = (float *)alloca(registerCount * 4 * sizeof(float));
|
||||
memcpy(data, values, count * sizeof(float));
|
||||
if (location.impl.shaderType == 0)
|
||||
device->SetVertexShaderConstantF(location.impl.reg.regindex, data, registerCount);
|
||||
else
|
||||
device->SetPixelShaderConstantF(location.impl.reg.regindex, data, registerCount);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_set_matrix4(kinc_g4_constant_location_t location, kinc_matrix4x4_t *value) {
|
||||
if (location.impl.shaderType == -1)
|
||||
return;
|
||||
float floats[16];
|
||||
for (int y = 0; y < 4; ++y) {
|
||||
for (int x = 0; x < 4; ++x) {
|
||||
floats[y * 4 + x] = kinc_matrix4x4_get(value, y, x);
|
||||
}
|
||||
}
|
||||
if (location.impl.shaderType == 0)
|
||||
device->SetVertexShaderConstantF(location.impl.reg.regindex, floats, 4);
|
||||
else
|
||||
device->SetPixelShaderConstantF(location.impl.reg.regindex, floats, 4);
|
||||
}
|
||||
|
||||
void kinc_g4_set_matrix3(kinc_g4_constant_location_t location, kinc_matrix3x3_t *value) {
|
||||
if (location.impl.shaderType == -1)
|
||||
return;
|
||||
float floats[12];
|
||||
for (int y = 0; y < 3; ++y) {
|
||||
for (int x = 0; x < 3; ++x) {
|
||||
floats[y * 4 + x] = kinc_matrix3x3_get(value, y, x);
|
||||
}
|
||||
}
|
||||
if (location.impl.shaderType == 0)
|
||||
device->SetVertexShaderConstantF(location.impl.reg.regindex, floats, 3);
|
||||
else
|
||||
device->SetPixelShaderConstantF(location.impl.reg.regindex, floats, 3);
|
||||
}
|
||||
|
||||
void kinc_g4_set_vertex_buffers(kinc_g4_vertex_buffer_t **buffers, int count) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
kinc_internal_g4_vertex_buffer_set(buffers[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_set_index_buffer(kinc_g4_index_buffer_t *buffer) {
|
||||
kinc_internal_g4_index_buffer_set(buffer);
|
||||
}
|
||||
|
||||
#ifdef KINC_KONG
|
||||
void kinc_internal_texture_set(kinc_g4_texture_t *texture, uint32_t unit);
|
||||
|
||||
void kinc_g4_set_texture(uint32_t unit, struct kinc_g4_texture *texture) {
|
||||
kinc_internal_texture_set(texture, unit);
|
||||
}
|
||||
#else
|
||||
void kinc_internal_texture_set(kinc_g4_texture_t *texture, kinc_g4_texture_unit_t unit);
|
||||
|
||||
void kinc_g4_set_texture(kinc_g4_texture_unit_t unit, struct kinc_g4_texture *texture) {
|
||||
kinc_internal_texture_set(texture, unit);
|
||||
}
|
||||
#endif
|
||||
|
||||
void kinc_g4_set_image_texture(kinc_g4_texture_unit_t unit, struct kinc_g4_texture *texture) {}
|
||||
|
||||
unsigned queryCount = 0;
|
||||
std::vector<IDirect3DQuery9 *> queryPool;
|
||||
|
||||
bool kinc_g4_init_occlusion_query(unsigned *occlusionQuery) {
|
||||
// check if the runtime supports queries
|
||||
HRESULT result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, NULL);
|
||||
if (FAILED(result)) {
|
||||
kinc_log(KINC_LOG_LEVEL_WARNING, "Internal query creation failed, result: 0x%X.", result);
|
||||
return false;
|
||||
}
|
||||
|
||||
IDirect3DQuery9 *pQuery = nullptr;
|
||||
device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &pQuery);
|
||||
|
||||
queryPool.push_back(pQuery);
|
||||
*occlusionQuery = queryCount;
|
||||
++queryCount;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void kinc_g4_delete_occlusion_query(unsigned occlusionQuery) {
|
||||
if (occlusionQuery < queryPool.size())
|
||||
queryPool[occlusionQuery] = nullptr;
|
||||
}
|
||||
|
||||
void kinc_g4_start_occlusion_query(unsigned occlusionQuery) {
|
||||
IDirect3DQuery9 *pQuery = queryPool[occlusionQuery];
|
||||
if (pQuery != nullptr) {
|
||||
pQuery->Issue(D3DISSUE_BEGIN);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_end_occlusion_query(unsigned occlusionQuery) {
|
||||
IDirect3DQuery9 *pQuery = queryPool[occlusionQuery];
|
||||
if (pQuery != nullptr) {
|
||||
pQuery->Issue(D3DISSUE_END);
|
||||
}
|
||||
}
|
||||
|
||||
bool kinc_g4_are_query_results_available(unsigned occlusionQuery) {
|
||||
IDirect3DQuery9 *pQuery = queryPool[occlusionQuery];
|
||||
if (pQuery != nullptr) {
|
||||
if (S_OK == pQuery->GetData(0, 0, 0)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void kinc_g4_get_query_results(unsigned occlusionQuery, unsigned *pixelCount) {
|
||||
IDirect3DQuery9 *pQuery = queryPool[occlusionQuery];
|
||||
if (pQuery != nullptr) {
|
||||
DWORD numberOfPixelsDrawn;
|
||||
HRESULT result = pQuery->GetData(&numberOfPixelsDrawn, sizeof(DWORD), 0);
|
||||
if (S_OK == result) {
|
||||
*pixelCount = numberOfPixelsDrawn;
|
||||
}
|
||||
else {
|
||||
kinc_log(KINC_LOG_LEVEL_WARNING, "Check first if results are available");
|
||||
*pixelCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture_array(kinc_g4_texture_unit_t unit, struct kinc_g4_texture_array *array) {}
|
||||
|
||||
void kinc_g4_set_pipeline(struct kinc_g4_pipeline *pipeline) {
|
||||
kinc_g4_internal_set_pipeline(pipeline);
|
||||
}
|
||||
|
||||
bool kinc_g4_supports_instanced_rendering() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool kinc_g4_supports_compute_shaders() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool kinc_g4_supports_blend_constants() {
|
||||
D3DCAPS9 pCaps = {};
|
||||
if (FAILED(device->GetDeviceCaps(&pCaps))) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Failed to get device caps");
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((pCaps.SrcBlendCaps & D3DPBLENDCAPS_BLENDFACTOR) != 0) && ((pCaps.DestBlendCaps & D3DPBLENDCAPS_BLENDFACTOR) != 0);
|
||||
}
|
||||
|
||||
bool kinc_g4_supports_non_pow2_textures() {
|
||||
D3DCAPS9 pCaps = {};
|
||||
if (FAILED(device->GetDeviceCaps(&pCaps))) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Failed to get device caps");
|
||||
return false;
|
||||
}
|
||||
// only advertise full npot support
|
||||
return ((pCaps.TextureCaps & D3DPTEXTURECAPS_POW2) == 0) && ((pCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) == 0);
|
||||
}
|
||||
|
||||
bool kinc_g4_render_targets_inverted_y(void) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void kinc_g4_set_constant_buffer(uint32_t id, struct kinc_g4_constant_buffer *buffer) {}
|
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/graphics4/graphics.h>
|
||||
#include <kinc/math/matrix.h>
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define D3D_DEBUG_INFO
|
||||
#endif
|
||||
#include <d3d9.h>
|
||||
|
||||
extern IDirect3D9 *d3d;
|
||||
extern IDirect3DDevice9 *device;
|
@ -0,0 +1,34 @@
|
||||
#ifdef KINC_KONG
|
||||
|
||||
#include <kinc/graphics4/constantbuffer.h>
|
||||
|
||||
#include "Direct3D9.h"
|
||||
|
||||
void kinc_g4_constant_buffer_init(kinc_g4_constant_buffer *buffer, size_t size) {
|
||||
buffer->impl.size = size;
|
||||
buffer->impl.last_start = 0;
|
||||
buffer->impl.last_size = size;
|
||||
}
|
||||
|
||||
void kinc_g4_constant_buffer_destroy(kinc_g4_constant_buffer *buffer) {}
|
||||
|
||||
uint8_t *kinc_g4_constant_buffer_lock_all(kinc_g4_constant_buffer *buffer) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint8_t *kinc_g4_constant_buffer_lock(kinc_g4_constant_buffer *buffer, size_t start, size_t size) {
|
||||
buffer->impl.last_start = start;
|
||||
buffer->impl.last_size = size;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void kinc_g4_constant_buffer_unlock_all(kinc_g4_constant_buffer *buffer) {}
|
||||
|
||||
void kinc_g4_constant_buffer_unlock(kinc_g4_constant_buffer *buffer, size_t count) {}
|
||||
|
||||
size_t kinc_g4_constant_buffer_size(kinc_g4_constant_buffer *buffer) {
|
||||
return buffer->impl.size;
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef KINC_KONG
|
||||
|
||||
typedef struct kinc_g4_constant_buffer_impl {
|
||||
size_t size;
|
||||
size_t last_start;
|
||||
size_t last_size;
|
||||
} kinc_g4_constant_buffer_impl;
|
||||
|
||||
#endif
|
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "IndexBufferImpl.h"
|
||||
#include "RenderTargetImpl.h"
|
||||
#include "ShaderImpl.h"
|
||||
#include "VertexBufferImpl.h"
|
@ -0,0 +1,56 @@
|
||||
#include <kinc/graphics4/graphics.h>
|
||||
#include <kinc/graphics4/indexbuffer.h>
|
||||
|
||||
#include <kinc/backend/SystemMicrosoft.h>
|
||||
|
||||
#include "Direct3D9.h"
|
||||
|
||||
struct kinc_g4_index_buffer *kinc_internal_current_index_buffer = NULL;
|
||||
|
||||
void kinc_g4_index_buffer_init(kinc_g4_index_buffer_t *buffer, int count, kinc_g4_index_buffer_format_t format, kinc_g4_usage_t usage) {
|
||||
buffer->impl.count = count;
|
||||
buffer->impl.format = format;
|
||||
|
||||
DWORD usageFlags = D3DUSAGE_WRITEONLY;
|
||||
if (usage == KINC_G4_USAGE_DYNAMIC) {
|
||||
usageFlags = D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY;
|
||||
}
|
||||
|
||||
kinc_microsoft_affirm(device->CreateIndexBuffer(
|
||||
sizeof(int) * count, usageFlags, format == KINC_G4_INDEX_BUFFER_FORMAT_32BIT ? D3DFMT_INDEX32 : D3DFMT_INDEX16, D3DPOOL_DEFAULT, &buffer->impl.ib, 0));
|
||||
}
|
||||
|
||||
void kinc_g4_index_buffer_destroy(kinc_g4_index_buffer_t *buffer) {
|
||||
buffer->impl.ib->Release();
|
||||
}
|
||||
|
||||
static int kinc_g4_internal_index_buffer_stride(kinc_g4_index_buffer_t *buffer) {
|
||||
return buffer->impl.format == KINC_G4_INDEX_BUFFER_FORMAT_32BIT ? 4 : 2;
|
||||
}
|
||||
|
||||
void *kinc_g4_index_buffer_lock_all(kinc_g4_index_buffer_t *buffer) {
|
||||
return kinc_g4_index_buffer_lock(buffer, 0, kinc_g4_index_buffer_count(buffer));
|
||||
}
|
||||
|
||||
void *kinc_g4_index_buffer_lock(kinc_g4_index_buffer_t *buffer, int start, int count) {
|
||||
uint8_t *data;
|
||||
kinc_microsoft_affirm(buffer->impl.ib->Lock(0, sizeof(int) * kinc_g4_index_buffer_count(buffer), (void **)&data, D3DLOCK_DISCARD));
|
||||
return &data[start * kinc_g4_internal_index_buffer_stride(buffer)];
|
||||
}
|
||||
|
||||
void kinc_g4_index_buffer_unlock_all(kinc_g4_index_buffer_t *buffer) {
|
||||
kinc_microsoft_affirm(buffer->impl.ib->Unlock());
|
||||
}
|
||||
|
||||
void kinc_g4_index_buffer_unlock(kinc_g4_index_buffer_t *buffer, int count) {
|
||||
kinc_g4_index_buffer_unlock_all(buffer);
|
||||
}
|
||||
|
||||
void kinc_internal_g4_index_buffer_set(kinc_g4_index_buffer_t *buffer) {
|
||||
kinc_internal_current_index_buffer = buffer;
|
||||
kinc_microsoft_affirm(device->SetIndices(buffer->impl.ib));
|
||||
}
|
||||
|
||||
int kinc_g4_index_buffer_count(kinc_g4_index_buffer_t *buffer) {
|
||||
return buffer->impl.count;
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct IDirect3DIndexBuffer9;
|
||||
|
||||
typedef struct {
|
||||
struct IDirect3DIndexBuffer9 *ib;
|
||||
int count;
|
||||
int format;
|
||||
} kinc_g4_index_buffer_impl_t;
|
||||
|
||||
struct kinc_g4_index_buffer;
|
||||
|
||||
extern struct kinc_g4_index_buffer *kinc_internal_current_index_buffer;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,365 @@
|
||||
#include <kinc/graphics4/graphics.h>
|
||||
#include <kinc/graphics4/pipeline.h>
|
||||
#include <kinc/graphics4/shader.h>
|
||||
#include <kinc/graphics4/vertexstructure.h>
|
||||
#include <kinc/log.h>
|
||||
#include <kinc/system.h>
|
||||
|
||||
#include <kinc/backend/SystemMicrosoft.h>
|
||||
|
||||
#include "Direct3D9.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <malloc.h>
|
||||
|
||||
namespace {
|
||||
_D3DBLEND convert_blend_factor(kinc_g4_blending_factor_t factor) {
|
||||
switch (factor) {
|
||||
case KINC_G4_BLEND_ONE:
|
||||
return D3DBLEND_ONE;
|
||||
case KINC_G4_BLEND_ZERO:
|
||||
return D3DBLEND_ZERO;
|
||||
case KINC_G4_BLEND_SOURCE_ALPHA:
|
||||
return D3DBLEND_SRCALPHA;
|
||||
case KINC_G4_BLEND_DEST_ALPHA:
|
||||
return D3DBLEND_DESTALPHA;
|
||||
case KINC_G4_BLEND_INV_SOURCE_ALPHA:
|
||||
return D3DBLEND_INVSRCALPHA;
|
||||
case KINC_G4_BLEND_INV_DEST_ALPHA:
|
||||
return D3DBLEND_INVDESTALPHA;
|
||||
case KINC_G4_BLEND_CONSTANT:
|
||||
return D3DBLEND_BLENDFACTOR;
|
||||
case KINC_G4_BLEND_INV_CONSTANT:
|
||||
return D3DBLEND_INVBLENDFACTOR;
|
||||
default:
|
||||
assert(false);
|
||||
return D3DBLEND_SRCALPHA;
|
||||
}
|
||||
}
|
||||
|
||||
_D3DBLENDOP convert_blend_operation(kinc_g4_blending_operation_t op) {
|
||||
switch (op) {
|
||||
case KINC_G4_BLENDOP_ADD:
|
||||
return D3DBLENDOP_ADD;
|
||||
case KINC_G4_BLENDOP_SUBTRACT:
|
||||
return D3DBLENDOP_SUBTRACT;
|
||||
case KINC_G4_BLENDOP_REVERSE_SUBTRACT:
|
||||
return D3DBLENDOP_REVSUBTRACT;
|
||||
case KINC_G4_BLENDOP_MIN:
|
||||
return D3DBLENDOP_MIN;
|
||||
case KINC_G4_BLENDOP_MAX:
|
||||
return D3DBLENDOP_MAX;
|
||||
default:
|
||||
assert(false);
|
||||
return D3DBLENDOP_ADD;
|
||||
}
|
||||
}
|
||||
|
||||
_D3DCMPFUNC convert(kinc_g4_compare_mode_t mode) {
|
||||
switch (mode) {
|
||||
default:
|
||||
case KINC_G4_COMPARE_ALWAYS:
|
||||
return D3DCMP_ALWAYS;
|
||||
case KINC_G4_COMPARE_NEVER:
|
||||
return D3DCMP_NEVER;
|
||||
case KINC_G4_COMPARE_EQUAL:
|
||||
return D3DCMP_EQUAL;
|
||||
case KINC_G4_COMPARE_NOT_EQUAL:
|
||||
return D3DCMP_NOTEQUAL;
|
||||
case KINC_G4_COMPARE_LESS:
|
||||
return D3DCMP_LESS;
|
||||
case KINC_G4_COMPARE_LESS_EQUAL:
|
||||
return D3DCMP_LESSEQUAL;
|
||||
case KINC_G4_COMPARE_GREATER:
|
||||
return D3DCMP_GREATER;
|
||||
case KINC_G4_COMPARE_GREATER_EQUAL:
|
||||
return D3DCMP_GREATEREQUAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_pipeline_init(kinc_g4_pipeline_t *state) {
|
||||
memset(state, 0, sizeof(kinc_g4_pipeline));
|
||||
kinc_g4_internal_pipeline_set_defaults(state);
|
||||
}
|
||||
|
||||
void kinc_g4_pipeline_destroy(kinc_g4_pipeline_t *state) {}
|
||||
|
||||
static int find_attribute(struct ShaderAttribute *attributes, const char *name) {
|
||||
for (int i = 0; i < KINC_INTERNAL_MAX_ATTRIBUTES; ++i) {
|
||||
if (attributes[i].name == 0) {
|
||||
return -1;
|
||||
}
|
||||
if (strcmp(attributes[i].name, name) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int find_constant(struct ShaderRegister *constants, const char *name) {
|
||||
for (int i = 0; i < KINC_INTERNAL_MAX_CONSTANTS; ++i) {
|
||||
if (constants[i].name == 0) {
|
||||
return -1;
|
||||
}
|
||||
if (strcmp(constants[i].name, name) == 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void kinc_g4_pipeline_compile(kinc_g4_pipeline_t *state) {
|
||||
int highestIndex = 0;
|
||||
for (int i = 0;; ++i) {
|
||||
if (state->vertex_shader->impl.attributes[i].name[0] == 0) {
|
||||
break;
|
||||
}
|
||||
int index = state->vertex_shader->impl.attributes[i].index;
|
||||
if (index > highestIndex) {
|
||||
highestIndex = index;
|
||||
}
|
||||
}
|
||||
|
||||
int all = 0;
|
||||
for (int stream = 0; state->input_layout[stream] != nullptr; ++stream) {
|
||||
for (int index = 0; index < state->input_layout[stream]->size; ++index) {
|
||||
if (state->input_layout[stream]->elements[index].data == KINC_G4_VERTEX_DATA_F32_4X4) {
|
||||
all += 4;
|
||||
}
|
||||
else {
|
||||
all += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
D3DVERTEXELEMENT9 *elements = (D3DVERTEXELEMENT9 *)_alloca(sizeof(D3DVERTEXELEMENT9) * (all + 1));
|
||||
int i = 0;
|
||||
for (int stream = 0; state->input_layout[stream] != nullptr; ++stream) {
|
||||
int stride = 0;
|
||||
for (int index = 0; index < state->input_layout[stream]->size; ++index) {
|
||||
if (state->input_layout[stream]->elements[index].data != KINC_G4_VERTEX_DATA_F32_4X4) {
|
||||
elements[i].Stream = stream;
|
||||
elements[i].Offset = stride;
|
||||
}
|
||||
stride += kinc_g4_vertex_data_size(state->input_layout[stream]->elements[index].data);
|
||||
switch (state->input_layout[stream]->elements[index].data) {
|
||||
case KINC_G4_VERTEX_DATA_F32_1X:
|
||||
elements[i].Type = D3DDECLTYPE_FLOAT1;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_F32_2X:
|
||||
elements[i].Type = D3DDECLTYPE_FLOAT2;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_F32_3X:
|
||||
elements[i].Type = D3DDECLTYPE_FLOAT3;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_F32_4X:
|
||||
elements[i].Type = D3DDECLTYPE_FLOAT4;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U8_4X:
|
||||
elements[i].Type = D3DDECLTYPE_UBYTE4;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U8_4X_NORMALIZED:
|
||||
elements[i].Type = D3DDECLTYPE_UBYTE4N;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I16_2X:
|
||||
elements[i].Type = D3DDECLTYPE_SHORT2;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I16_2X_NORMALIZED:
|
||||
elements[i].Type = D3DDECLTYPE_SHORT2N;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U16_2X_NORMALIZED:
|
||||
elements[i].Type = D3DDECLTYPE_USHORT2N;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I16_4X:
|
||||
elements[i].Type = D3DDECLTYPE_SHORT4;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I16_4X_NORMALIZED:
|
||||
elements[i].Type = D3DDECLTYPE_SHORT4N;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_U16_4X_NORMALIZED:
|
||||
elements[i].Type = D3DDECLTYPE_USHORT4N;
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_I8_1X:
|
||||
case KINC_G4_VERTEX_DATA_U8_1X:
|
||||
case KINC_G4_VERTEX_DATA_I8_1X_NORMALIZED:
|
||||
case KINC_G4_VERTEX_DATA_U8_1X_NORMALIZED:
|
||||
case KINC_G4_VERTEX_DATA_I8_2X:
|
||||
case KINC_G4_VERTEX_DATA_U8_2X:
|
||||
case KINC_G4_VERTEX_DATA_I8_2X_NORMALIZED:
|
||||
case KINC_G4_VERTEX_DATA_U8_2X_NORMALIZED:
|
||||
case KINC_G4_VERTEX_DATA_I8_4X:
|
||||
case KINC_G4_VERTEX_DATA_I8_4X_NORMALIZED:
|
||||
case KINC_G4_VERTEX_DATA_I16_1X:
|
||||
case KINC_G4_VERTEX_DATA_U16_1X:
|
||||
case KINC_G4_VERTEX_DATA_I16_1X_NORMALIZED:
|
||||
case KINC_G4_VERTEX_DATA_U16_1X_NORMALIZED:
|
||||
case KINC_G4_VERTEX_DATA_U16_2X:
|
||||
case KINC_G4_VERTEX_DATA_U16_4X:
|
||||
case KINC_G4_VERTEX_DATA_I32_1X:
|
||||
case KINC_G4_VERTEX_DATA_U32_1X:
|
||||
case KINC_G4_VERTEX_DATA_I32_2X:
|
||||
case KINC_G4_VERTEX_DATA_U32_2X:
|
||||
case KINC_G4_VERTEX_DATA_I32_3X:
|
||||
case KINC_G4_VERTEX_DATA_U32_3X:
|
||||
case KINC_G4_VERTEX_DATA_I32_4X:
|
||||
case KINC_G4_VERTEX_DATA_U32_4X:
|
||||
elements[i].Type = D3DDECLTYPE_UNUSED;
|
||||
assert(false);
|
||||
break;
|
||||
case KINC_G4_VERTEX_DATA_F32_4X4:
|
||||
for (int i2 = 0; i2 < 4; ++i2) {
|
||||
elements[i].Stream = stream;
|
||||
elements[i].Offset = stride;
|
||||
elements[i].Type = D3DDECLTYPE_FLOAT4;
|
||||
elements[i].Method = D3DDECLMETHOD_DEFAULT;
|
||||
elements[i].Usage = D3DDECLUSAGE_TEXCOORD;
|
||||
char name[101];
|
||||
strcpy(name, state->input_layout[stream]->elements[index].name);
|
||||
strcat(name, "_");
|
||||
size_t length = strlen(name);
|
||||
_itoa(i2, &name[length], 10);
|
||||
name[length + 1] = 0;
|
||||
int attribute_index = find_attribute(state->vertex_shader->impl.attributes, name);
|
||||
if (attribute_index < 0) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Could not find attribute %s.", name);
|
||||
elements[i].UsageIndex = ++highestIndex;
|
||||
}
|
||||
else {
|
||||
elements[i].UsageIndex = state->vertex_shader->impl.attributes[attribute_index].index;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (state->input_layout[stream]->elements[index].data != KINC_G4_VERTEX_DATA_F32_4X4) {
|
||||
elements[i].Method = D3DDECLMETHOD_DEFAULT;
|
||||
elements[i].Usage = D3DDECLUSAGE_TEXCOORD;
|
||||
int attribute_index = find_attribute(state->vertex_shader->impl.attributes, state->input_layout[stream]->elements[index].name);
|
||||
if (attribute_index < 0) {
|
||||
kinc_log(KINC_LOG_LEVEL_ERROR, "Could not find attribute %s.", state->input_layout[stream]->elements[index].name);
|
||||
elements[i].UsageIndex = ++highestIndex;
|
||||
}
|
||||
else {
|
||||
elements[i].UsageIndex = state->vertex_shader->impl.attributes[attribute_index].index;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
elements[all].Stream = 0xff;
|
||||
elements[all].Offset = 0;
|
||||
elements[all].Type = D3DDECLTYPE_UNUSED;
|
||||
elements[all].Method = 0;
|
||||
elements[all].Usage = 0;
|
||||
elements[all].UsageIndex = 0;
|
||||
|
||||
state->impl.vertexDecleration = nullptr;
|
||||
kinc_microsoft_affirm(device->CreateVertexDeclaration(elements, &state->impl.vertexDecleration));
|
||||
|
||||
int constant_index = find_constant(state->vertex_shader->impl.constants, "gl_HalfPixel");
|
||||
state->impl.halfPixelLocation = state->vertex_shader->impl.constants[constant_index].regindex;
|
||||
}
|
||||
|
||||
void kinc_g4_internal_set_pipeline(kinc_g4_pipeline_t *pipeline) {
|
||||
kinc_microsoft_affirm(device->SetVertexShader((IDirect3DVertexShader9 *)pipeline->vertex_shader->impl.shader));
|
||||
kinc_microsoft_affirm(device->SetPixelShader((IDirect3DPixelShader9 *)pipeline->fragment_shader->impl.shader));
|
||||
kinc_microsoft_affirm(device->SetVertexDeclaration(pipeline->impl.vertexDecleration));
|
||||
|
||||
// TODO (DK) System::screenWidth/Height are only main-window dimensions, what about other windows?
|
||||
float floats[4];
|
||||
floats[0] = 1.0f / kinc_width();
|
||||
floats[1] = 1.0f / kinc_height();
|
||||
floats[2] = floats[0];
|
||||
floats[3] = floats[1];
|
||||
kinc_microsoft_affirm(device->SetVertexShaderConstantF(pipeline->impl.halfPixelLocation, floats, 1));
|
||||
|
||||
DWORD flags = 0;
|
||||
if (pipeline->color_write_mask_red[0]) {
|
||||
flags |= D3DCOLORWRITEENABLE_RED;
|
||||
}
|
||||
if (pipeline->color_write_mask_green[0]) {
|
||||
flags |= D3DCOLORWRITEENABLE_GREEN;
|
||||
}
|
||||
if (pipeline->color_write_mask_blue[0]) {
|
||||
flags |= D3DCOLORWRITEENABLE_BLUE;
|
||||
}
|
||||
if (pipeline->color_write_mask_alpha[0]) {
|
||||
flags |= D3DCOLORWRITEENABLE_ALPHA;
|
||||
}
|
||||
|
||||
device->SetRenderState(D3DRS_COLORWRITEENABLE, flags);
|
||||
|
||||
device->SetRenderState(D3DRS_ALPHABLENDENABLE,
|
||||
(pipeline->blend_source != KINC_G4_BLEND_ONE || pipeline->blend_destination != KINC_G4_BLEND_ZERO) ? TRUE : FALSE);
|
||||
device->SetRenderState(D3DRS_SRCBLEND, convert_blend_factor(pipeline->blend_source));
|
||||
device->SetRenderState(D3DRS_DESTBLEND, convert_blend_factor(pipeline->blend_destination));
|
||||
device->SetRenderState(D3DRS_BLENDOP, convert_blend_operation(pipeline->blend_operation));
|
||||
|
||||
switch (pipeline->cull_mode) {
|
||||
case KINC_G4_CULL_CLOCKWISE:
|
||||
device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
|
||||
break;
|
||||
case KINC_G4_CULL_COUNTER_CLOCKWISE:
|
||||
device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
|
||||
break;
|
||||
case KINC_G4_CULL_NOTHING:
|
||||
device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
|
||||
break;
|
||||
}
|
||||
|
||||
device->SetRenderState(D3DRS_ZENABLE, pipeline->depth_mode != KINC_G4_COMPARE_ALWAYS ? TRUE : FALSE);
|
||||
device->SetRenderState(D3DRS_ZFUNC, convert(pipeline->depth_mode));
|
||||
device->SetRenderState(D3DRS_ZWRITEENABLE, pipeline->depth_write ? TRUE : FALSE);
|
||||
|
||||
/*
|
||||
case AlphaTestState:
|
||||
device->SetRenderState(D3DRS_ALPHATESTENABLE, on ? TRUE : FALSE);
|
||||
device->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
|
||||
break;
|
||||
case AlphaReferenceState:
|
||||
device->SetRenderState(D3DRS_ALPHAREF, (DWORD)v);
|
||||
break;
|
||||
*/
|
||||
}
|
||||
|
||||
kinc_g4_constant_location_t kinc_g4_pipeline_get_constant_location(kinc_g4_pipeline_t *state, const char *name) {
|
||||
kinc_g4_constant_location_t location;
|
||||
|
||||
int fragment_index = find_constant(state->fragment_shader->impl.constants, name);
|
||||
int vertex_index = find_constant(state->vertex_shader->impl.constants, name);
|
||||
|
||||
if (fragment_index >= 0) {
|
||||
location.impl.reg = state->fragment_shader->impl.constants[fragment_index];
|
||||
location.impl.shaderType = 1;
|
||||
}
|
||||
else if (vertex_index >= 0) {
|
||||
location.impl.reg = state->vertex_shader->impl.constants[vertex_index];
|
||||
location.impl.shaderType = 0;
|
||||
}
|
||||
else {
|
||||
location.impl.shaderType = -1;
|
||||
kinc_log(KINC_LOG_LEVEL_WARNING, "Could not find uniform %s.", name);
|
||||
}
|
||||
return location;
|
||||
}
|
||||
|
||||
kinc_g4_texture_unit_t kinc_g4_pipeline_get_texture_unit(kinc_g4_pipeline_t *state, const char *name) {
|
||||
int fragment_index = find_constant(state->fragment_shader->impl.constants, name);
|
||||
int vertex_index = find_constant(state->vertex_shader->impl.constants, name);
|
||||
|
||||
kinc_g4_texture_unit_t unit;
|
||||
for (int i = 0; i < KINC_G4_SHADER_TYPE_COUNT; ++i) {
|
||||
unit.stages[i] = -1;
|
||||
}
|
||||
|
||||
if (fragment_index >= 0) {
|
||||
unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT] = state->fragment_shader->impl.constants[fragment_index].regindex;
|
||||
}
|
||||
|
||||
if (vertex_index >= 0) {
|
||||
unit.stages[KINC_G4_SHADER_TYPE_VERTEX] = state->vertex_shader->impl.constants[vertex_index].regindex;
|
||||
}
|
||||
|
||||
return unit;
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct IDirect3DVertexDeclaration9;
|
||||
|
||||
typedef struct {
|
||||
struct IDirect3DVertexDeclaration9 *vertexDecleration;
|
||||
int halfPixelLocation;
|
||||
} kinc_g4_pipeline_impl_t;
|
||||
|
||||
void kinc_internal_set_constants(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,133 @@
|
||||
#include <kinc/graphics4/rendertarget.h>
|
||||
#include <kinc/log.h>
|
||||
|
||||
#include <kinc/backend/SystemMicrosoft.h>
|
||||
|
||||
#include "Direct3D9.h"
|
||||
|
||||
void kinc_g4_render_target_init_with_multisampling(kinc_g4_render_target_t *renderTarget, int width, int height, kinc_g4_render_target_format_t format,
|
||||
int depthBufferBits, int stencilBufferBits, int samples_per_pixel) {
|
||||
renderTarget->width = width;
|
||||
renderTarget->height = height;
|
||||
renderTarget->texWidth = width;
|
||||
renderTarget->texHeight = height;
|
||||
renderTarget->isCubeMap = false;
|
||||
renderTarget->isDepthAttachment = false;
|
||||
|
||||
const bool antialiasing = samples_per_pixel > 1;
|
||||
renderTarget->impl.antialiasing = antialiasing;
|
||||
|
||||
D3DFORMAT d3dformat;
|
||||
switch (format) {
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_64BIT_FLOAT:
|
||||
d3dformat = D3DFMT_A16B16G16R16F;
|
||||
break;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_32BIT_RED_FLOAT:
|
||||
d3dformat = D3DFMT_R32F;
|
||||
break;
|
||||
case KINC_G4_RENDER_TARGET_FORMAT_32BIT:
|
||||
default:
|
||||
d3dformat = D3DFMT_A8R8G8B8;
|
||||
}
|
||||
|
||||
#if defined(_DEBUG)
|
||||
kinc_log(KINC_LOG_LEVEL_INFO, "depthBufferBits not implemented yet, using defaults (D3DFMT_D24S8)");
|
||||
kinc_log(KINC_LOG_LEVEL_INFO, "stencilBufferBits not implemented yet, using defaults (D3DFMT_D24S8)");
|
||||
#endif
|
||||
|
||||
renderTarget->impl.colorSurface = nullptr;
|
||||
renderTarget->impl.depthSurface = nullptr;
|
||||
renderTarget->impl.colorTexture = nullptr;
|
||||
renderTarget->impl.depthTexture = nullptr;
|
||||
|
||||
if (antialiasing) {
|
||||
kinc_microsoft_affirm(
|
||||
device->CreateRenderTarget(width, height, d3dformat, D3DMULTISAMPLE_8_SAMPLES, 0, FALSE, &renderTarget->impl.colorSurface, nullptr));
|
||||
kinc_microsoft_affirm(
|
||||
device->CreateDepthStencilSurface(width, height, D3DFMT_D24S8, D3DMULTISAMPLE_8_SAMPLES, 0, TRUE, &renderTarget->impl.depthSurface, nullptr));
|
||||
kinc_microsoft_affirm(
|
||||
device->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET, d3dformat, D3DPOOL_DEFAULT, &renderTarget->impl.colorTexture, nullptr));
|
||||
// Microsoft::affirm(device->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &depthTexture, nullptr));
|
||||
renderTarget->impl.depthTexture = nullptr;
|
||||
}
|
||||
else {
|
||||
if (format == KINC_G4_RENDER_TARGET_FORMAT_16BIT_DEPTH) {
|
||||
kinc_microsoft_affirm(device->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET, (D3DFORMAT)MAKEFOURCC('N', 'U', 'L', 'L'), D3DPOOL_DEFAULT,
|
||||
&renderTarget->impl.colorTexture, nullptr));
|
||||
kinc_microsoft_affirm(device->CreateTexture(width, height, 1, D3DUSAGE_DEPTHSTENCIL, (D3DFORMAT)MAKEFOURCC('I', 'N', 'T', 'Z'), D3DPOOL_DEFAULT,
|
||||
&renderTarget->impl.depthTexture, nullptr));
|
||||
renderTarget->isDepthAttachment = true;
|
||||
}
|
||||
else {
|
||||
kinc_microsoft_affirm(
|
||||
device->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET, d3dformat, D3DPOOL_DEFAULT, &renderTarget->impl.colorTexture, nullptr));
|
||||
kinc_microsoft_affirm(
|
||||
device->CreateTexture(width, height, 1, D3DUSAGE_DEPTHSTENCIL, D3DFMT_D24S8, D3DPOOL_DEFAULT, &renderTarget->impl.depthTexture, nullptr));
|
||||
}
|
||||
kinc_microsoft_affirm(renderTarget->impl.colorTexture->GetSurfaceLevel(0, &renderTarget->impl.colorSurface));
|
||||
kinc_microsoft_affirm(renderTarget->impl.depthTexture->GetSurfaceLevel(0, &renderTarget->impl.depthSurface));
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_init_cube_with_multisampling(kinc_g4_render_target_t *renderTarget, int cubeMapSize, kinc_g4_render_target_format_t format,
|
||||
int depthBufferBits, int stencilBufferBits, int samples_per_pixel) {
|
||||
renderTarget->isCubeMap = true;
|
||||
renderTarget->isDepthAttachment = false;
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_destroy(kinc_g4_render_target_t *renderTarget) {
|
||||
if (renderTarget->impl.colorSurface != nullptr) {
|
||||
renderTarget->impl.colorSurface->Release();
|
||||
}
|
||||
if (renderTarget->impl.depthSurface != nullptr) {
|
||||
renderTarget->impl.depthSurface->Release();
|
||||
}
|
||||
if (renderTarget->impl.colorTexture != nullptr) {
|
||||
renderTarget->impl.colorTexture->Release();
|
||||
}
|
||||
if (renderTarget->impl.depthTexture != nullptr) {
|
||||
renderTarget->impl.depthTexture->Release();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef KINC_KONG
|
||||
void kinc_g4_render_target_use_color_as_texture(kinc_g4_render_target_t *renderTarget, uint32_t unit) {
|
||||
if (renderTarget->impl.antialiasing) {
|
||||
IDirect3DSurface9 *surface;
|
||||
renderTarget->impl.colorTexture->GetSurfaceLevel(0, &surface);
|
||||
kinc_microsoft_affirm(device->StretchRect(renderTarget->impl.colorSurface, nullptr, surface, nullptr, D3DTEXF_NONE));
|
||||
surface->Release();
|
||||
}
|
||||
device->SetTexture(unit, renderTarget->isDepthAttachment ? renderTarget->impl.depthTexture : renderTarget->impl.colorTexture);
|
||||
}
|
||||
#else
|
||||
void kinc_g4_render_target_use_color_as_texture(kinc_g4_render_target_t *renderTarget, kinc_g4_texture_unit_t unit) {
|
||||
if (renderTarget->impl.antialiasing) {
|
||||
IDirect3DSurface9 *surface;
|
||||
renderTarget->impl.colorTexture->GetSurfaceLevel(0, &surface);
|
||||
kinc_microsoft_affirm(device->StretchRect(renderTarget->impl.colorSurface, nullptr, surface, nullptr, D3DTEXF_NONE));
|
||||
surface->Release();
|
||||
}
|
||||
device->SetTexture(unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT],
|
||||
renderTarget->isDepthAttachment ? renderTarget->impl.depthTexture : renderTarget->impl.colorTexture);
|
||||
}
|
||||
#endif
|
||||
|
||||
void kinc_g4_render_target_set_depth_stencil_from(kinc_g4_render_target_t *renderTarget, kinc_g4_render_target_t *source) {
|
||||
renderTarget->impl.depthTexture = source->impl.depthTexture;
|
||||
renderTarget->impl.depthSurface = source->impl.depthSurface;
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_use_depth_as_texture(kinc_g4_render_target_t *renderTarget, kinc_g4_texture_unit_t unit) {
|
||||
if (renderTarget->impl.antialiasing) {
|
||||
IDirect3DSurface9 *surface;
|
||||
renderTarget->impl.depthTexture->GetSurfaceLevel(0, &surface);
|
||||
kinc_microsoft_affirm(device->StretchRect(renderTarget->impl.depthSurface, nullptr, surface, nullptr, D3DTEXF_NONE));
|
||||
surface->Release();
|
||||
}
|
||||
device->SetTexture(unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], renderTarget->impl.depthTexture);
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_get_pixels(kinc_g4_render_target_t *renderTarget, uint8_t *data) {}
|
||||
|
||||
void kinc_g4_render_target_generate_mipmaps(kinc_g4_render_target_t *renderTarget, int levels) {}
|
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct IDirect3DSurface9;
|
||||
struct IDirect3DTexture9;
|
||||
|
||||
typedef struct {
|
||||
struct IDirect3DSurface9 *colorSurface;
|
||||
struct IDirect3DSurface9 *depthSurface;
|
||||
struct IDirect3DTexture9 *colorTexture;
|
||||
struct IDirect3DTexture9 *depthTexture;
|
||||
bool antialiasing;
|
||||
} kinc_g4_render_target_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,54 @@
|
||||
#include <kinc/graphics4/shader.h>
|
||||
#include <kinc/math/core.h>
|
||||
|
||||
#include <kinc/backend/SystemMicrosoft.h>
|
||||
|
||||
#include "Direct3D9.h"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
void kinc_g4_shader_init(kinc_g4_shader_t *shader, const void *void_data, size_t length, kinc_g4_shader_type_t type) {
|
||||
unsigned index = 0;
|
||||
|
||||
uint8_t *data = (uint8_t *)void_data;
|
||||
int attributesCount = data[index++];
|
||||
for (int i = 0; i < attributesCount; ++i) {
|
||||
char name[256];
|
||||
for (unsigned i2 = 0; i2 < 255; ++i2) {
|
||||
name[i2] = data[index++];
|
||||
if (name[i2] == 0)
|
||||
break;
|
||||
}
|
||||
strcpy(shader->impl.attributes[i].name, name);
|
||||
shader->impl.attributes[i].index = data[index++];
|
||||
}
|
||||
shader->impl.attributes[attributesCount].name[0] = 0;
|
||||
|
||||
uint8_t constantCount = data[index++];
|
||||
for (unsigned i = 0; i < constantCount; ++i) {
|
||||
char name[256];
|
||||
for (unsigned i2 = 0; i2 < 255; ++i2) {
|
||||
name[i2] = data[index++];
|
||||
if (name[i2] == 0)
|
||||
break;
|
||||
}
|
||||
strcpy(shader->impl.constants[i].name, name);
|
||||
shader->impl.constants[i].regtype = data[index++];
|
||||
shader->impl.constants[i].regindex = data[index++];
|
||||
shader->impl.constants[i].regcount = data[index++];
|
||||
}
|
||||
shader->impl.constants[constantCount].name[0] = 0;
|
||||
|
||||
if (type == KINC_G4_SHADER_TYPE_VERTEX) {
|
||||
kinc_microsoft_affirm(device->CreateVertexShader((DWORD *)&data[index], (IDirect3DVertexShader9 **)&shader));
|
||||
}
|
||||
else {
|
||||
kinc_microsoft_affirm(device->CreatePixelShader((DWORD *)&data[index], (IDirect3DPixelShader9 **)&shader));
|
||||
}
|
||||
}
|
||||
|
||||
int kinc_g4_shader_init_from_source(kinc_g4_shader_t *shader, const char *source, kinc_g4_shader_type_t type) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
void kinc_g4_shader_destroy(kinc_g4_shader_t *shader) {}
|
@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ShaderRegister {
|
||||
char name[128];
|
||||
uint8_t regtype;
|
||||
uint8_t regindex;
|
||||
uint8_t regcount;
|
||||
};
|
||||
|
||||
struct ShaderAttribute {
|
||||
char name[128];
|
||||
int index;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
struct ShaderRegister reg;
|
||||
int shaderType; // 0: Vertex, 1: Fragment
|
||||
} kinc_g4_constant_location_impl_t;
|
||||
|
||||
typedef struct {
|
||||
int unit;
|
||||
} kinc_g4_texture_unit_impl_t;
|
||||
|
||||
#define KINC_INTERNAL_MAX_CONSTANTS 64
|
||||
#define KINC_INTERNAL_MAX_ATTRIBUTES 64
|
||||
|
||||
typedef struct {
|
||||
struct ShaderRegister constants[KINC_INTERNAL_MAX_CONSTANTS];
|
||||
struct ShaderAttribute attributes[KINC_INTERNAL_MAX_ATTRIBUTES];
|
||||
void *shader;
|
||||
} kinc_g4_shader_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,110 @@
|
||||
#include <kinc/graphics4/texture.h>
|
||||
#include <kinc/io/filereader.h>
|
||||
|
||||
#include <kinc/backend/SystemMicrosoft.h>
|
||||
|
||||
#include "Direct3D9.h"
|
||||
|
||||
namespace {
|
||||
kinc_g4_texture_t *setTextures[16] = {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr};
|
||||
|
||||
D3DFORMAT convert(kinc_image_format_t format) {
|
||||
switch (format) {
|
||||
case KINC_IMAGE_FORMAT_RGBA32:
|
||||
default:
|
||||
return D3DFMT_A8R8G8B8;
|
||||
case KINC_IMAGE_FORMAT_GREY8:
|
||||
return D3DFMT_L8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_texture_init_from_image(kinc_g4_texture_t *texture, kinc_image_t *image) {
|
||||
texture->impl.stage = 0;
|
||||
texture->impl.mipmap = true;
|
||||
DWORD usage = 0;
|
||||
texture->tex_width = image->width;
|
||||
texture->tex_height = image->height;
|
||||
texture->tex_depth = 1;
|
||||
usage = D3DUSAGE_DYNAMIC;
|
||||
kinc_microsoft_affirm_message(
|
||||
device->CreateTexture(image->width, image->height, 1, usage, convert(image->format), D3DPOOL_DEFAULT, &texture->impl.texture, 0),
|
||||
"Texture creation failed.");
|
||||
D3DLOCKED_RECT rect;
|
||||
kinc_microsoft_affirm(texture->impl.texture->LockRect(0, &rect, 0, 0));
|
||||
texture->impl.pitch = rect.Pitch;
|
||||
uint8_t *from = (uint8_t *)image->data;
|
||||
uint8_t *to = (uint8_t *)rect.pBits;
|
||||
// memcpy(to, from, width * height * sizeOf(format));
|
||||
for (int y = 0; y < image->height; ++y) {
|
||||
for (int x = 0; x < image->width; ++x) {
|
||||
to[rect.Pitch * y + x * 4 + 0 /* blue*/] = (from[y * image->width * 4 + x * 4 + 2]); /// 255.0f;
|
||||
to[rect.Pitch * y + x * 4 + 1 /*green*/] = (from[y * image->width * 4 + x * 4 + 1]); /// 255.0f;
|
||||
to[rect.Pitch * y + x * 4 + 2 /* red*/] = (from[y * image->width * 4 + x * 4 + 0]); /// 255.0f;
|
||||
to[rect.Pitch * y + x * 4 + 3 /*alpha*/] = (from[y * image->width * 4 + x * 4 + 3]); /// 255.0f;
|
||||
}
|
||||
}
|
||||
kinc_microsoft_affirm(texture->impl.texture->UnlockRect(0));
|
||||
}
|
||||
|
||||
void kinc_g4_texture_init3d(kinc_g4_texture_t *texture, int width, int height, int depth, kinc_image_format_t format) {}
|
||||
|
||||
void kinc_g4_texture_init(kinc_g4_texture_t *texture, int width, int height, kinc_image_format_t format) {
|
||||
texture->impl.stage = 0;
|
||||
texture->impl.mipmap = true;
|
||||
DWORD usage = 0;
|
||||
texture->tex_width = width;
|
||||
texture->tex_height = height;
|
||||
texture->tex_depth = 1;
|
||||
usage = D3DUSAGE_DYNAMIC;
|
||||
kinc_microsoft_affirm_message(device->CreateTexture(width, height, 1, usage, convert(format), D3DPOOL_DEFAULT, &texture->impl.texture, 0),
|
||||
"Texture creation failed.");
|
||||
}
|
||||
|
||||
void kinc_g4_texture_destroy(kinc_g4_texture_t *texture) {
|
||||
kinc_internal_texture_unset(texture);
|
||||
texture->impl.texture->Release();
|
||||
}
|
||||
|
||||
#ifdef KINC_KONG
|
||||
void kinc_internal_texture_set(kinc_g4_texture_t *texture, uint32_t unit) {
|
||||
kinc_microsoft_affirm(device->SetTexture(unit, texture->impl.texture));
|
||||
texture->impl.stage = unit;
|
||||
setTextures[texture->impl.stage] = texture;
|
||||
}
|
||||
#else
|
||||
void kinc_internal_texture_set(kinc_g4_texture_t *texture, kinc_g4_texture_unit_t unit) {
|
||||
kinc_microsoft_affirm(device->SetTexture(unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT], texture->impl.texture));
|
||||
texture->impl.stage = unit.stages[KINC_G4_SHADER_TYPE_FRAGMENT];
|
||||
setTextures[texture->impl.stage] = texture;
|
||||
}
|
||||
#endif
|
||||
|
||||
void kinc_internal_texture_unset(struct kinc_g4_texture *texture) {
|
||||
if (setTextures[texture->impl.stage] == texture) {
|
||||
device->SetTexture(texture->impl.stage, nullptr);
|
||||
setTextures[texture->impl.stage] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char *kinc_g4_texture_lock(kinc_g4_texture_t *texture) {
|
||||
D3DLOCKED_RECT rect;
|
||||
kinc_microsoft_affirm(texture->impl.texture->LockRect(0, &rect, 0, 0));
|
||||
texture->impl.pitch = rect.Pitch;
|
||||
return (uint8_t *)rect.pBits;
|
||||
}
|
||||
|
||||
void kinc_g4_texture_unlock(kinc_g4_texture_t *texture) {
|
||||
kinc_microsoft_affirm(texture->impl.texture->UnlockRect(0));
|
||||
}
|
||||
|
||||
void kinc_g4_texture_clear(kinc_g4_texture_t *texture, int x, int y, int z, int width, int height, int depth, unsigned color) {}
|
||||
|
||||
int kinc_g4_texture_stride(kinc_g4_texture_t *texture) {
|
||||
return texture->impl.pitch;
|
||||
}
|
||||
|
||||
void kinc_g4_texture_generate_mipmaps(kinc_g4_texture_t *texture, int levels) {}
|
||||
|
||||
void kinc_g4_texture_set_mipmap(kinc_g4_texture_t *texture, kinc_image_t *mipmap, int level) {}
|
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct IDirect3DTexture9;
|
||||
|
||||
typedef struct {
|
||||
struct IDirect3DTexture9 *texture;
|
||||
int stage;
|
||||
bool mipmap;
|
||||
uint8_t pixfmt;
|
||||
int pitch;
|
||||
} kinc_g4_texture_impl_t;
|
||||
|
||||
struct kinc_g4_texture;
|
||||
|
||||
void kinc_internal_texture_unmipmap(struct kinc_g4_texture *texture);
|
||||
void kinc_internal_texture_unset(struct kinc_g4_texture *texture);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,5 @@
|
||||
#include <kinc/graphics4/texturearray.h>
|
||||
|
||||
void kinc_g4_texture_array_init(kinc_g4_texture_array_t *array, kinc_image_t *textures, int count) {}
|
||||
|
||||
void kinc_g4_texture_array_destroy(kinc_g4_texture_array_t *array) {}
|
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
int nothing;
|
||||
} kinc_g4_texture_array_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,75 @@
|
||||
#include <kinc/graphics4/graphics.h>
|
||||
#include <kinc/graphics4/vertexbuffer.h>
|
||||
|
||||
#include <kinc/backend/SystemMicrosoft.h>
|
||||
|
||||
#include "Direct3D9.h"
|
||||
|
||||
struct kinc_g4_vertex_buffer *kinc_internal_current_vertex_buffer = NULL;
|
||||
|
||||
void kinc_g4_vertex_buffer_init(kinc_g4_vertex_buffer_t *buffer, int count, kinc_g4_vertex_structure_t *structure, kinc_g4_usage_t usage,
|
||||
int instance_data_step_rate) {
|
||||
buffer->impl.myCount = count;
|
||||
buffer->impl.instanceDataStepRate = instance_data_step_rate;
|
||||
DWORD usageFlags = D3DUSAGE_WRITEONLY;
|
||||
if (usage == KINC_G4_USAGE_DYNAMIC) {
|
||||
usageFlags = D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY;
|
||||
}
|
||||
|
||||
buffer->impl.myStride = 0;
|
||||
for (int i = 0; i < structure->size; ++i) {
|
||||
buffer->impl.myStride += kinc_g4_vertex_data_size(structure->elements[i].data);
|
||||
}
|
||||
|
||||
kinc_microsoft_affirm(device->CreateVertexBuffer(kinc_g4_vertex_buffer_stride(buffer) * count, usageFlags, 0, D3DPOOL_DEFAULT, &buffer->impl.vb, 0));
|
||||
}
|
||||
|
||||
void kinc_g4_vertex_buffer_destroy(kinc_g4_vertex_buffer_t *buffer) {
|
||||
buffer->impl.vb->Release();
|
||||
}
|
||||
|
||||
float *kinc_g4_vertex_buffer_lock_all(kinc_g4_vertex_buffer_t *buffer) {
|
||||
return kinc_g4_vertex_buffer_lock(buffer, 0, kinc_g4_vertex_buffer_count(buffer));
|
||||
}
|
||||
|
||||
float *kinc_g4_vertex_buffer_lock(kinc_g4_vertex_buffer_t *buffer, int start, int count) {
|
||||
float *vertices;
|
||||
kinc_internal_vertex_buffer_unset(buffer);
|
||||
kinc_microsoft_affirm(buffer->impl.vb->Lock(start, count * kinc_g4_vertex_buffer_stride(buffer), (void **)&vertices, D3DLOCK_DISCARD));
|
||||
return vertices;
|
||||
}
|
||||
|
||||
void kinc_g4_vertex_buffer_unlock_all(kinc_g4_vertex_buffer_t *buffer) {
|
||||
kinc_microsoft_affirm(buffer->impl.vb->Unlock());
|
||||
}
|
||||
|
||||
void kinc_g4_vertex_buffer_unlock(kinc_g4_vertex_buffer_t *buffer, int count) {
|
||||
kinc_microsoft_affirm(buffer->impl.vb->Unlock());
|
||||
}
|
||||
|
||||
int kinc_internal_g4_vertex_buffer_set(kinc_g4_vertex_buffer_t *buffer, int offset) {
|
||||
buffer->impl._offset = offset;
|
||||
if (buffer->impl.instanceDataStepRate == 0) {
|
||||
kinc_internal_current_vertex_buffer = buffer;
|
||||
}
|
||||
else {
|
||||
kinc_microsoft_affirm(device->SetStreamSourceFreq(offset, (D3DSTREAMSOURCE_INSTANCEDATA | buffer->impl.instanceDataStepRate)));
|
||||
}
|
||||
kinc_microsoft_affirm(device->SetStreamSource(offset, buffer->impl.vb, 0, kinc_g4_vertex_buffer_stride(buffer)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void kinc_internal_vertex_buffer_unset(struct kinc_g4_vertex_buffer *buffer) {
|
||||
if (kinc_internal_current_vertex_buffer == buffer) {
|
||||
kinc_microsoft_affirm(device->SetStreamSource(0, NULL, 0, 0));
|
||||
kinc_internal_current_vertex_buffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int kinc_g4_vertex_buffer_count(kinc_g4_vertex_buffer_t *buffer) {
|
||||
return buffer->impl.myCount;
|
||||
}
|
||||
|
||||
int kinc_g4_vertex_buffer_stride(kinc_g4_vertex_buffer_t *buffer) {
|
||||
return buffer->impl.myStride;
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct IDirect3DVertexBuffer9;
|
||||
|
||||
typedef struct {
|
||||
struct IDirect3DVertexBuffer9 *vb;
|
||||
int myCount;
|
||||
int myStride;
|
||||
int instanceDataStepRate;
|
||||
int _offset;
|
||||
} kinc_g4_vertex_buffer_impl_t;
|
||||
|
||||
struct kinc_g4_vertex_buffer;
|
||||
|
||||
void kinc_internal_vertex_buffer_unset(struct kinc_g4_vertex_buffer *buffer);
|
||||
|
||||
extern struct kinc_g4_vertex_buffer *kinc_internal_current_vertex_buffer;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,841 @@
|
||||
#include "G4.h"
|
||||
#include "kinc/graphics4/graphics.h"
|
||||
#include "kinc/window.h"
|
||||
|
||||
#include <kinc/backend/graphics4/indexbuffer.h>
|
||||
#include <kinc/backend/graphics4/pipeline.h>
|
||||
#include <kinc/backend/graphics4/vertexbuffer.h>
|
||||
#include <kinc/color.h>
|
||||
#include <kinc/graphics4/compute.h>
|
||||
#include <kinc/graphics4/constantbuffer.h>
|
||||
#include <kinc/graphics4/indexbuffer.h>
|
||||
#include <kinc/graphics4/pipeline.h>
|
||||
#include <kinc/graphics4/rendertarget.h>
|
||||
#include <kinc/graphics4/shader.h>
|
||||
#include <kinc/graphics4/texture.h>
|
||||
#include <kinc/graphics4/texturearray.h>
|
||||
#include <kinc/graphics4/vertexbuffer.h>
|
||||
#include <kinc/graphics5/commandlist.h>
|
||||
#include <kinc/graphics5/constantbuffer.h>
|
||||
#include <kinc/graphics5/graphics.h>
|
||||
#include <kinc/graphics5/sampler.h>
|
||||
#include <kinc/io/filereader.h>
|
||||
#include <kinc/math/core.h>
|
||||
#include <kinc/math/matrix.h>
|
||||
#include <kinc/system.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
kinc_g5_command_list_t commandList;
|
||||
|
||||
uint64_t frameNumber = 0;
|
||||
bool waitAfterNextDraw = false;
|
||||
|
||||
static kinc_g5_constant_buffer_t vertexConstantBuffer;
|
||||
static kinc_g5_constant_buffer_t fragmentConstantBuffer;
|
||||
#define constantBufferSize 4096
|
||||
#define constantBufferMultiply 100
|
||||
static int constantBufferIndex = 0;
|
||||
|
||||
void kinc_g4_internal_init(void) {
|
||||
kinc_g5_internal_init();
|
||||
}
|
||||
|
||||
void kinc_g4_internal_destroy(void) {
|
||||
kinc_g5_internal_destroy();
|
||||
}
|
||||
|
||||
void kinc_g4_internal_destroy_window(int window) {
|
||||
kinc_g5_internal_destroy_window(window);
|
||||
}
|
||||
|
||||
#define bufferCount 2
|
||||
#define renderTargetCount 8
|
||||
|
||||
static struct {
|
||||
int currentBuffer;
|
||||
kinc_g5_render_target_t framebuffers[bufferCount];
|
||||
|
||||
kinc_g4_render_target_t *current_render_targets[renderTargetCount];
|
||||
int current_render_target_count;
|
||||
|
||||
bool resized;
|
||||
} windows[16] = {0};
|
||||
|
||||
static int current_window;
|
||||
|
||||
#define MAX_VERTEX_BUFFERS 16
|
||||
#define MAX_TEXTURES 16
|
||||
|
||||
typedef struct render_state {
|
||||
kinc_g5_pipeline_t *pipeline;
|
||||
|
||||
kinc_g5_index_buffer_t *index_buffer;
|
||||
|
||||
kinc_g5_vertex_buffer_t *vertex_buffers[MAX_VERTEX_BUFFERS];
|
||||
int vertex_buffer_offsets[MAX_VERTEX_BUFFERS];
|
||||
int vertex_buffer_count;
|
||||
|
||||
bool blend_constant_set;
|
||||
float blend_constant_r;
|
||||
float blend_constant_g;
|
||||
float blend_constant_b;
|
||||
float blend_constant_a;
|
||||
|
||||
bool viewport_set;
|
||||
int viewport_x;
|
||||
int viewport_y;
|
||||
int viewport_width;
|
||||
int viewport_height;
|
||||
|
||||
bool scissor_set;
|
||||
int scissor_x;
|
||||
int scissor_y;
|
||||
int scissor_width;
|
||||
int scissor_height;
|
||||
|
||||
kinc_g5_texture_t *textures[MAX_TEXTURES];
|
||||
kinc_g5_texture_unit_t texture_units[MAX_TEXTURES];
|
||||
int texture_count;
|
||||
|
||||
kinc_g5_render_target_t *render_targets[MAX_TEXTURES];
|
||||
kinc_g5_texture_unit_t render_target_units[MAX_TEXTURES];
|
||||
int render_target_count;
|
||||
|
||||
kinc_g5_render_target_t *depth_render_targets[MAX_TEXTURES];
|
||||
kinc_g5_texture_unit_t depth_render_target_units[MAX_TEXTURES];
|
||||
int depth_render_target_count;
|
||||
|
||||
uint8_t vertex_constant_data[constantBufferSize];
|
||||
uint8_t fragment_constant_data[constantBufferSize];
|
||||
} render_state;
|
||||
|
||||
static render_state current_state;
|
||||
|
||||
void kinc_g4_on_g5_internal_resize(int window, int width, int height) {
|
||||
windows[window].resized = true;
|
||||
}
|
||||
|
||||
void kinc_g4_on_g5_internal_restore_render_target(void) {
|
||||
windows[current_window].current_render_targets[0] = NULL;
|
||||
kinc_g5_render_target_t *render_target = &windows[current_window].framebuffers[windows[current_window].currentBuffer];
|
||||
kinc_g5_command_list_set_render_targets(&commandList, &render_target, 1);
|
||||
windows[current_window].current_render_target_count = 1;
|
||||
}
|
||||
|
||||
void kinc_g4_internal_init_window(int window, int depthBufferBits, int stencilBufferBits, bool vsync) {
|
||||
kinc_g5_internal_init_window(window, depthBufferBits, stencilBufferBits, vsync);
|
||||
|
||||
kinc_g5_command_list_init(&commandList);
|
||||
windows[window].currentBuffer = -1;
|
||||
for (int i = 0; i < bufferCount; ++i) {
|
||||
kinc_g5_render_target_init_framebuffer(&windows[window].framebuffers[i], kinc_window_width(window), kinc_window_height(window),
|
||||
KINC_G5_RENDER_TARGET_FORMAT_32BIT, depthBufferBits, 0);
|
||||
}
|
||||
kinc_g5_constant_buffer_init(&vertexConstantBuffer, constantBufferSize * constantBufferMultiply);
|
||||
kinc_g5_constant_buffer_init(&fragmentConstantBuffer, constantBufferSize * constantBufferMultiply);
|
||||
|
||||
// to support doing work after kinc_g4_end and before kinc_g4_begin
|
||||
kinc_g5_command_list_begin(&commandList);
|
||||
}
|
||||
|
||||
void kinc_g4_on_g5_internal_set_samplers(int count, kinc_g5_texture_unit_t *texture_units) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
for (int j = 0; j < KINC_G5_SHADER_TYPE_COUNT; ++j) {
|
||||
if (texture_units[i].stages[j] >= 0) {
|
||||
kinc_g5_sampler_t *sampler = get_current_sampler(j, texture_units[i].stages[j]);
|
||||
kinc_g5_texture_unit_t unit;
|
||||
for (int k = 0; k < KINC_G5_SHADER_TYPE_COUNT; ++k) {
|
||||
unit.stages[k] = -1;
|
||||
}
|
||||
unit.stages[j] = texture_units[i].stages[j];
|
||||
kinc_g5_command_list_set_sampler(&commandList, unit, sampler);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void startDraw(void) {
|
||||
if ((constantBufferIndex + 1) >= constantBufferMultiply || waitAfterNextDraw) {
|
||||
memcpy(current_state.vertex_constant_data, vertexConstantBuffer.data, constantBufferSize);
|
||||
memcpy(current_state.fragment_constant_data, fragmentConstantBuffer.data, constantBufferSize);
|
||||
}
|
||||
kinc_g5_constant_buffer_unlock(&vertexConstantBuffer);
|
||||
kinc_g5_constant_buffer_unlock(&fragmentConstantBuffer);
|
||||
|
||||
kinc_g4_on_g5_internal_set_samplers(current_state.texture_count, current_state.texture_units);
|
||||
kinc_g4_on_g5_internal_set_samplers(current_state.render_target_count, current_state.render_target_units);
|
||||
kinc_g4_on_g5_internal_set_samplers(current_state.depth_render_target_count, current_state.depth_render_target_units);
|
||||
|
||||
kinc_g5_command_list_set_vertex_constant_buffer(&commandList, &vertexConstantBuffer, constantBufferIndex * constantBufferSize, constantBufferSize);
|
||||
kinc_g5_command_list_set_fragment_constant_buffer(&commandList, &fragmentConstantBuffer, constantBufferIndex * constantBufferSize, constantBufferSize);
|
||||
}
|
||||
|
||||
static void endDraw(void) {
|
||||
++constantBufferIndex;
|
||||
if (constantBufferIndex >= constantBufferMultiply || waitAfterNextDraw) {
|
||||
kinc_g5_command_list_end(&commandList);
|
||||
kinc_g5_command_list_execute(&commandList);
|
||||
kinc_g5_command_list_wait_for_execution_to_finish(&commandList);
|
||||
kinc_g5_command_list_begin(&commandList);
|
||||
if (windows[current_window].current_render_targets[0] == NULL) {
|
||||
kinc_g4_on_g5_internal_restore_render_target();
|
||||
}
|
||||
else {
|
||||
const int count = windows[current_window].current_render_target_count;
|
||||
kinc_g5_render_target_t *render_targets[16];
|
||||
for (int i = 0; i < count; ++i) {
|
||||
render_targets[i] = &windows[current_window].current_render_targets[i]->impl._renderTarget;
|
||||
}
|
||||
kinc_g5_command_list_set_render_targets(&commandList, render_targets, count);
|
||||
}
|
||||
|
||||
if (current_state.pipeline != NULL) {
|
||||
kinc_g5_command_list_set_pipeline(&commandList, current_state.pipeline);
|
||||
}
|
||||
if (current_state.index_buffer != NULL) {
|
||||
kinc_g5_command_list_set_index_buffer(&commandList, current_state.index_buffer);
|
||||
}
|
||||
if (current_state.vertex_buffer_count > 0) {
|
||||
kinc_g5_command_list_set_vertex_buffers(&commandList, current_state.vertex_buffers, current_state.vertex_buffer_offsets,
|
||||
current_state.vertex_buffer_count);
|
||||
}
|
||||
if (current_state.blend_constant_set) {
|
||||
kinc_g5_command_list_set_blend_constant(&commandList, current_state.blend_constant_r, current_state.blend_constant_g,
|
||||
current_state.blend_constant_b, current_state.blend_constant_a);
|
||||
}
|
||||
if (current_state.viewport_set) {
|
||||
kinc_g5_command_list_viewport(&commandList, current_state.viewport_x, current_state.viewport_y, current_state.viewport_width,
|
||||
current_state.viewport_height);
|
||||
}
|
||||
if (current_state.scissor_set) {
|
||||
kinc_g5_command_list_scissor(&commandList, current_state.scissor_x, current_state.scissor_y, current_state.scissor_width,
|
||||
current_state.scissor_height);
|
||||
}
|
||||
for (int i = 0; i < current_state.texture_count; ++i) {
|
||||
kinc_g5_command_list_set_texture(&commandList, current_state.texture_units[i], current_state.textures[i]);
|
||||
}
|
||||
for (int i = 0; i < current_state.render_target_count; ++i) {
|
||||
kinc_g5_command_list_set_texture_from_render_target(&commandList, current_state.render_target_units[i], current_state.render_targets[i]);
|
||||
}
|
||||
for (int i = 0; i < current_state.depth_render_target_count; ++i) {
|
||||
kinc_g5_command_list_set_texture_from_render_target_depth(&commandList, current_state.depth_render_target_units[i],
|
||||
current_state.depth_render_targets[i]);
|
||||
}
|
||||
constantBufferIndex = 0;
|
||||
waitAfterNextDraw = false;
|
||||
|
||||
kinc_g5_constant_buffer_lock(&vertexConstantBuffer, 0, constantBufferSize);
|
||||
kinc_g5_constant_buffer_lock(&fragmentConstantBuffer, 0, constantBufferSize);
|
||||
|
||||
memcpy(vertexConstantBuffer.data, current_state.vertex_constant_data, constantBufferSize);
|
||||
memcpy(fragmentConstantBuffer.data, current_state.fragment_constant_data, constantBufferSize);
|
||||
}
|
||||
else {
|
||||
kinc_g5_constant_buffer_lock(&vertexConstantBuffer, constantBufferIndex * constantBufferSize, constantBufferSize);
|
||||
kinc_g5_constant_buffer_lock(&fragmentConstantBuffer, constantBufferIndex * constantBufferSize, constantBufferSize);
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_draw_indexed_vertices(void) {
|
||||
startDraw();
|
||||
kinc_g5_command_list_draw_indexed_vertices(&commandList);
|
||||
endDraw();
|
||||
}
|
||||
|
||||
void kinc_g4_draw_indexed_vertices_from_to(int start, int count) {
|
||||
startDraw();
|
||||
kinc_g5_command_list_draw_indexed_vertices_from_to(&commandList, start, count);
|
||||
endDraw();
|
||||
}
|
||||
|
||||
void kinc_g4_draw_indexed_vertices_from_to_from(int start, int count, int vertex_offset) {
|
||||
startDraw();
|
||||
kinc_g5_command_list_draw_indexed_vertices_from_to_from(&commandList, start, count, vertex_offset);
|
||||
endDraw();
|
||||
}
|
||||
|
||||
void kinc_g4_draw_indexed_vertices_instanced(int instanceCount) {
|
||||
startDraw();
|
||||
kinc_g5_command_list_draw_indexed_vertices_instanced(&commandList, instanceCount);
|
||||
endDraw();
|
||||
}
|
||||
|
||||
void kinc_g4_draw_indexed_vertices_instanced_from_to(int instanceCount, int start, int count) {
|
||||
startDraw();
|
||||
kinc_g5_command_list_draw_indexed_vertices_instanced_from_to(&commandList, instanceCount, start, count);
|
||||
endDraw();
|
||||
}
|
||||
|
||||
void kinc_g4_clear(unsigned flags, unsigned color, float depth, int stencil) {
|
||||
if (windows[current_window].current_render_target_count > 0) {
|
||||
if (windows[current_window].current_render_targets[0] == NULL) {
|
||||
kinc_g5_command_list_clear(&commandList, &windows[current_window].framebuffers[windows[current_window].currentBuffer], flags, color, depth,
|
||||
stencil);
|
||||
}
|
||||
else {
|
||||
if (windows[current_window].current_render_targets[0]->impl.state != KINC_INTERNAL_RENDER_TARGET_STATE_RENDER_TARGET) {
|
||||
kinc_g5_command_list_texture_to_render_target_barrier(&commandList, &windows[current_window].current_render_targets[0]->impl._renderTarget);
|
||||
windows[current_window].current_render_targets[0]->impl.state = KINC_INTERNAL_RENDER_TARGET_STATE_RENDER_TARGET;
|
||||
}
|
||||
kinc_g5_command_list_clear(&commandList, &windows[current_window].current_render_targets[0]->impl._renderTarget, flags, color, depth, stencil);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool first_run = true;
|
||||
|
||||
void kinc_g4_begin(int window) {
|
||||
// to support doing work after kinc_g4_end and before kinc_g4_begin
|
||||
kinc_g5_command_list_end(&commandList);
|
||||
kinc_g5_command_list_execute(&commandList);
|
||||
|
||||
current_window = window;
|
||||
|
||||
windows[current_window].currentBuffer = (windows[current_window].currentBuffer + 1) % bufferCount;
|
||||
|
||||
bool resized = windows[window].resized;
|
||||
if (resized) {
|
||||
for (int i = 0; i < bufferCount; ++i) {
|
||||
kinc_g5_render_target_destroy(&windows[current_window].framebuffers[i]);
|
||||
}
|
||||
windows[current_window].currentBuffer = 0;
|
||||
}
|
||||
|
||||
kinc_g5_begin(&windows[current_window].framebuffers[windows[current_window].currentBuffer], window);
|
||||
|
||||
if (resized) {
|
||||
for (int i = 0; i < bufferCount; ++i) {
|
||||
kinc_g5_render_target_init_framebuffer(&windows[current_window].framebuffers[i], kinc_window_width(window), kinc_window_height(window),
|
||||
KINC_G5_RENDER_TARGET_FORMAT_32BIT, 16, 0);
|
||||
}
|
||||
windows[window].resized = false;
|
||||
}
|
||||
|
||||
windows[current_window].current_render_targets[0] = NULL;
|
||||
windows[current_window].current_render_target_count = 1;
|
||||
|
||||
current_state.pipeline = NULL;
|
||||
current_state.index_buffer = NULL;
|
||||
for (int i = 0; i < MAX_VERTEX_BUFFERS; ++i) {
|
||||
current_state.vertex_buffers[i] = NULL;
|
||||
current_state.vertex_buffer_offsets[i] = 0;
|
||||
}
|
||||
current_state.vertex_buffer_count = 0;
|
||||
current_state.blend_constant_set = false;
|
||||
current_state.viewport_set = false;
|
||||
current_state.scissor_set = false;
|
||||
current_state.texture_count = 0;
|
||||
current_state.render_target_count = 0;
|
||||
current_state.depth_render_target_count = 0;
|
||||
|
||||
samplers_reset();
|
||||
|
||||
// commandList = new Graphics5::CommandList;
|
||||
kinc_g5_command_list_begin(&commandList);
|
||||
|
||||
// Currently we do not necessarily wait at the end of a frame so for now it's endDraw
|
||||
// constantBufferIndex = 0;
|
||||
// kinc_g5_constant_buffer_lock(&vertexConstantBuffer, 0, constantBufferSize);
|
||||
// kinc_g5_constant_buffer_lock(&fragmentConstantBuffer, 0, constantBufferSize);
|
||||
endDraw();
|
||||
|
||||
kinc_g5_command_list_framebuffer_to_render_target_barrier(&commandList, &windows[current_window].framebuffers[windows[current_window].currentBuffer]);
|
||||
kinc_g4_restore_render_target();
|
||||
|
||||
++frameNumber;
|
||||
}
|
||||
|
||||
void kinc_g4_viewport(int x, int y, int width, int height) {
|
||||
current_state.viewport_x = x;
|
||||
current_state.viewport_y = y;
|
||||
current_state.viewport_width = width;
|
||||
current_state.viewport_height = height;
|
||||
current_state.viewport_set = true;
|
||||
kinc_g5_command_list_viewport(&commandList, x, y, width, height);
|
||||
}
|
||||
|
||||
void kinc_g4_scissor(int x, int y, int width, int height) {
|
||||
current_state.scissor_x = x;
|
||||
current_state.scissor_y = y;
|
||||
current_state.scissor_width = width;
|
||||
current_state.scissor_height = height;
|
||||
current_state.scissor_set = true;
|
||||
kinc_g5_command_list_scissor(&commandList, x, y, width, height);
|
||||
}
|
||||
|
||||
void kinc_g4_disable_scissor(void) {
|
||||
current_state.scissor_set = false;
|
||||
kinc_g5_command_list_disable_scissor(&commandList);
|
||||
}
|
||||
|
||||
void kinc_g4_end(int window) {
|
||||
kinc_g5_constant_buffer_unlock(&vertexConstantBuffer);
|
||||
kinc_g5_constant_buffer_unlock(&fragmentConstantBuffer);
|
||||
|
||||
kinc_g5_command_list_render_target_to_framebuffer_barrier(&commandList, &windows[current_window].framebuffers[windows[current_window].currentBuffer]);
|
||||
kinc_g5_command_list_end(&commandList);
|
||||
kinc_g5_command_list_execute(&commandList);
|
||||
|
||||
// delete commandList;
|
||||
// commandList = nullptr;
|
||||
kinc_g5_end(window);
|
||||
|
||||
// to support doing work after kinc_g4_end and before kinc_g4_begin
|
||||
kinc_g5_command_list_begin(&commandList);
|
||||
}
|
||||
|
||||
/*void Graphics4::_changeFramebuffer(int window, Kore::FramebufferOptions* frame) {
|
||||
|
||||
}*/
|
||||
|
||||
bool kinc_g4_swap_buffers(void) {
|
||||
return kinc_g5_swap_buffers();
|
||||
}
|
||||
|
||||
void kinc_g4_flush(void) {
|
||||
kinc_g5_flush();
|
||||
}
|
||||
|
||||
void kinc_g4_set_stencil_reference_value(int value) {}
|
||||
|
||||
void kinc_g4_set_int(kinc_g4_constant_location_t location, int value) {
|
||||
if (location.impl._location.impl.vertexOffset >= 0)
|
||||
kinc_g5_constant_buffer_set_int(&vertexConstantBuffer, location.impl._location.impl.vertexOffset, value);
|
||||
if (location.impl._location.impl.fragmentOffset >= 0)
|
||||
kinc_g5_constant_buffer_set_int(&fragmentConstantBuffer, location.impl._location.impl.fragmentOffset, value);
|
||||
}
|
||||
|
||||
void kinc_g4_set_int2(kinc_g4_constant_location_t location, int value1, int value2) {}
|
||||
|
||||
void kinc_g4_set_int3(kinc_g4_constant_location_t location, int value1, int value2, int value3) {}
|
||||
|
||||
void kinc_g4_set_int4(kinc_g4_constant_location_t location, int value1, int value2, int value3, int value4) {}
|
||||
|
||||
void kinc_g4_set_ints(kinc_g4_constant_location_t location, int *values, int count) {}
|
||||
|
||||
void kinc_g4_set_float(kinc_g4_constant_location_t location, float value) {
|
||||
if (location.impl._location.impl.vertexOffset >= 0)
|
||||
kinc_g5_constant_buffer_set_float(&vertexConstantBuffer, location.impl._location.impl.vertexOffset, value);
|
||||
if (location.impl._location.impl.fragmentOffset >= 0)
|
||||
kinc_g5_constant_buffer_set_float(&fragmentConstantBuffer, location.impl._location.impl.fragmentOffset, value);
|
||||
}
|
||||
|
||||
void kinc_g4_set_float2(kinc_g4_constant_location_t location, float value1, float value2) {
|
||||
if (location.impl._location.impl.vertexOffset >= 0)
|
||||
kinc_g5_constant_buffer_set_float2(&vertexConstantBuffer, location.impl._location.impl.vertexOffset, value1, value2);
|
||||
if (location.impl._location.impl.fragmentOffset >= 0)
|
||||
kinc_g5_constant_buffer_set_float2(&fragmentConstantBuffer, location.impl._location.impl.fragmentOffset, value1, value2);
|
||||
}
|
||||
|
||||
void kinc_g4_set_float3(kinc_g4_constant_location_t location, float value1, float value2, float value3) {
|
||||
if (location.impl._location.impl.vertexOffset >= 0)
|
||||
kinc_g5_constant_buffer_set_float3(&vertexConstantBuffer, location.impl._location.impl.vertexOffset, value1, value2, value3);
|
||||
if (location.impl._location.impl.fragmentOffset >= 0)
|
||||
kinc_g5_constant_buffer_set_float3(&fragmentConstantBuffer, location.impl._location.impl.fragmentOffset, value1, value2, value3);
|
||||
}
|
||||
|
||||
void kinc_g4_set_float4(kinc_g4_constant_location_t location, float value1, float value2, float value3, float value4) {
|
||||
if (location.impl._location.impl.vertexOffset >= 0)
|
||||
kinc_g5_constant_buffer_set_float4(&vertexConstantBuffer, location.impl._location.impl.vertexOffset, value1, value2, value3, value4);
|
||||
if (location.impl._location.impl.fragmentOffset >= 0)
|
||||
kinc_g5_constant_buffer_set_float4(&fragmentConstantBuffer, location.impl._location.impl.fragmentOffset, value1, value2, value3, value4);
|
||||
}
|
||||
|
||||
void kinc_g4_set_floats(kinc_g4_constant_location_t location, float *values, int count) {
|
||||
if (location.impl._location.impl.vertexOffset >= 0)
|
||||
kinc_g5_constant_buffer_set_floats(&vertexConstantBuffer, location.impl._location.impl.vertexOffset, values, count);
|
||||
if (location.impl._location.impl.fragmentOffset >= 0)
|
||||
kinc_g5_constant_buffer_set_floats(&fragmentConstantBuffer, location.impl._location.impl.fragmentOffset, values, count);
|
||||
}
|
||||
|
||||
void kinc_g4_set_bool(kinc_g4_constant_location_t location, bool value) {
|
||||
if (location.impl._location.impl.vertexOffset >= 0)
|
||||
kinc_g5_constant_buffer_set_bool(&vertexConstantBuffer, location.impl._location.impl.vertexOffset, value);
|
||||
if (location.impl._location.impl.fragmentOffset >= 0)
|
||||
kinc_g5_constant_buffer_set_bool(&fragmentConstantBuffer, location.impl._location.impl.fragmentOffset, value);
|
||||
}
|
||||
|
||||
void kinc_g4_set_matrix4(kinc_g4_constant_location_t location, kinc_matrix4x4_t *value) {
|
||||
if (location.impl._location.impl.vertexOffset >= 0)
|
||||
kinc_g5_constant_buffer_set_matrix4(&vertexConstantBuffer, location.impl._location.impl.vertexOffset, value);
|
||||
if (location.impl._location.impl.fragmentOffset >= 0)
|
||||
kinc_g5_constant_buffer_set_matrix4(&fragmentConstantBuffer, location.impl._location.impl.fragmentOffset, value);
|
||||
}
|
||||
|
||||
void kinc_g4_set_matrix3(kinc_g4_constant_location_t location, kinc_matrix3x3_t *value) {
|
||||
if (location.impl._location.impl.vertexOffset >= 0)
|
||||
kinc_g5_constant_buffer_set_matrix3(&vertexConstantBuffer, location.impl._location.impl.vertexOffset, value);
|
||||
if (location.impl._location.impl.fragmentOffset >= 0)
|
||||
kinc_g5_constant_buffer_set_matrix3(&fragmentConstantBuffer, location.impl._location.impl.fragmentOffset, value);
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture_addressing(kinc_g4_texture_unit_t unit, kinc_g4_texture_direction_t dir, kinc_g4_texture_addressing_t addressing) {
|
||||
for (int i = 0; i < KINC_G5_SHADER_TYPE_COUNT; ++i) {
|
||||
if (unit.stages[i] >= 0) {
|
||||
if (dir == KINC_G4_TEXTURE_DIRECTION_U) {
|
||||
sampler_options[i][unit.stages[i]].u_addressing = (kinc_g5_texture_addressing_t)addressing;
|
||||
}
|
||||
if (dir == KINC_G4_TEXTURE_DIRECTION_V) {
|
||||
sampler_options[i][unit.stages[i]].v_addressing = (kinc_g5_texture_addressing_t)addressing;
|
||||
}
|
||||
if (dir == KINC_G4_TEXTURE_DIRECTION_W) {
|
||||
sampler_options[i][unit.stages[i]].w_addressing = (kinc_g5_texture_addressing_t)addressing;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture3d_addressing(kinc_g4_texture_unit_t unit, kinc_g4_texture_direction_t dir, kinc_g4_texture_addressing_t addressing) {
|
||||
kinc_g4_set_texture_addressing(unit, dir, addressing);
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture_magnification_filter(kinc_g4_texture_unit_t texunit, kinc_g4_texture_filter_t filter) {
|
||||
for (int i = 0; i < KINC_G5_SHADER_TYPE_COUNT; ++i) {
|
||||
if (texunit.stages[i] >= 0) {
|
||||
sampler_options[i][texunit.stages[i]].magnification_filter = (kinc_g5_texture_filter_t)filter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture3d_magnification_filter(kinc_g4_texture_unit_t texunit, kinc_g4_texture_filter_t filter) {
|
||||
kinc_g4_set_texture_magnification_filter(texunit, filter);
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture_minification_filter(kinc_g4_texture_unit_t texunit, kinc_g4_texture_filter_t filter) {
|
||||
for (int i = 0; i < KINC_G5_SHADER_TYPE_COUNT; ++i) {
|
||||
if (texunit.stages[i] >= 0) {
|
||||
sampler_options[i][texunit.stages[i]].minification_filter = (kinc_g5_texture_filter_t)filter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture3d_minification_filter(kinc_g4_texture_unit_t texunit, kinc_g4_texture_filter_t filter) {
|
||||
kinc_g4_set_texture_minification_filter(texunit, filter);
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture_mipmap_filter(kinc_g4_texture_unit_t texunit, kinc_g4_mipmap_filter_t filter) {
|
||||
for (int i = 0; i < KINC_G5_SHADER_TYPE_COUNT; ++i) {
|
||||
if (texunit.stages[i] >= 0) {
|
||||
sampler_options[i][texunit.stages[i]].mipmap_filter = (kinc_g5_mipmap_filter_t)filter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture3d_mipmap_filter(kinc_g4_texture_unit_t texunit, kinc_g4_mipmap_filter_t filter) {
|
||||
kinc_g4_set_texture_mipmap_filter(texunit, filter);
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture_compare_mode(kinc_g4_texture_unit_t unit, bool enabled) {
|
||||
for (int i = 0; i < KINC_G5_SHADER_TYPE_COUNT; ++i) {
|
||||
if (unit.stages[i] >= 0) {
|
||||
sampler_options[i][unit.stages[i]].is_comparison = enabled;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture_compare_func(kinc_g4_texture_unit_t unit, kinc_g4_compare_mode_t mode) {
|
||||
for (int i = 0; i < KINC_G5_SHADER_TYPE_COUNT; ++i) {
|
||||
if (unit.stages[i] >= 0) {
|
||||
sampler_options[i][unit.stages[i]].compare_mode = (kinc_g5_compare_mode_t)mode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_set_cubemap_compare_mode(kinc_g4_texture_unit_t unit, bool enabled) {}
|
||||
void kinc_g4_set_cubemap_compare_func(kinc_g4_texture_unit_t unit, kinc_g4_compare_mode_t mode) {}
|
||||
|
||||
void kinc_g4_set_texture_max_anisotropy(kinc_g4_texture_unit_t unit, uint16_t max_anisotropy) {
|
||||
for (int i = 0; i < KINC_G5_SHADER_TYPE_COUNT; ++i) {
|
||||
if (unit.stages[i] >= 0) {
|
||||
sampler_options[i][unit.stages[i]].max_anisotropy = max_anisotropy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_set_cubemap_max_anisotropy(kinc_g4_texture_unit_t unit, uint16_t max_anisotropy) {}
|
||||
|
||||
void kinc_g4_set_texture_lod(kinc_g4_texture_unit_t unit, float lod_min_clamp, float lod_max_clamp) {
|
||||
for (int i = 0; i < KINC_G5_SHADER_TYPE_COUNT; ++i) {
|
||||
if (unit.stages[i] >= 0) {
|
||||
sampler_options[i][unit.stages[i]].lod_min_clamp = lod_min_clamp;
|
||||
sampler_options[i][unit.stages[i]].lod_max_clamp = lod_max_clamp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kinc_g4_set_cubemap_lod(kinc_g4_texture_unit_t unit, float lod_min_clamp, float lod_max_clamp) {}
|
||||
|
||||
void kinc_g4_restore_render_target(void) {
|
||||
kinc_g4_on_g5_internal_restore_render_target();
|
||||
current_state.viewport_set = false;
|
||||
current_state.scissor_set = false;
|
||||
}
|
||||
|
||||
void kinc_g4_set_render_targets(kinc_g4_render_target_t **targets, int count) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
windows[current_window].current_render_targets[i] = targets[i];
|
||||
if (windows[current_window].current_render_targets[i]->impl.state != KINC_INTERNAL_RENDER_TARGET_STATE_RENDER_TARGET) {
|
||||
kinc_g5_command_list_texture_to_render_target_barrier(&commandList, &windows[current_window].current_render_targets[i]->impl._renderTarget);
|
||||
windows[current_window].current_render_targets[i]->impl.state = KINC_INTERNAL_RENDER_TARGET_STATE_RENDER_TARGET;
|
||||
}
|
||||
}
|
||||
windows[current_window].current_render_target_count = count;
|
||||
kinc_g5_render_target_t *render_targets[16];
|
||||
assert(count <= 16);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
render_targets[i] = &targets[i]->impl._renderTarget;
|
||||
}
|
||||
kinc_g5_command_list_set_render_targets(&commandList, render_targets, count);
|
||||
current_state.viewport_set = false;
|
||||
current_state.scissor_set = false;
|
||||
}
|
||||
|
||||
void kinc_g4_set_render_target_face(kinc_g4_render_target_t *texture, int face) {
|
||||
kinc_g5_command_list_set_render_target_face(&commandList, &texture->impl._renderTarget, face);
|
||||
current_state.viewport_set = false;
|
||||
current_state.scissor_set = false;
|
||||
}
|
||||
|
||||
void kinc_g4_set_vertex_buffers(kinc_g4_vertex_buffer_t **buffers, int count) {
|
||||
assert(count <= MAX_VERTEX_BUFFERS);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
current_state.vertex_buffers[i] = &buffers[i]->impl._buffer;
|
||||
int index = buffers[i]->impl._currentIndex;
|
||||
current_state.vertex_buffer_offsets[i] = index * kinc_g4_vertex_buffer_count(buffers[i]);
|
||||
}
|
||||
current_state.vertex_buffer_count = count;
|
||||
kinc_g5_command_list_set_vertex_buffers(&commandList, current_state.vertex_buffers, current_state.vertex_buffer_offsets, count);
|
||||
}
|
||||
|
||||
int kinc_internal_g4_vertex_buffer_set(kinc_g4_vertex_buffer_t *buffer, int offset) {
|
||||
kinc_g4_vertex_buffer_t *buffers[1];
|
||||
buffers[0] = buffer;
|
||||
kinc_g4_set_vertex_buffers(buffers, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void kinc_g4_set_index_buffer(kinc_g4_index_buffer_t *buffer) {
|
||||
kinc_g5_index_buffer_t *g5_index_buffer = &buffer->impl._buffer;
|
||||
current_state.index_buffer = g5_index_buffer;
|
||||
kinc_g5_command_list_set_index_buffer(&commandList, g5_index_buffer);
|
||||
}
|
||||
|
||||
#ifdef KINC_KONG
|
||||
void kinc_g4_set_texture(uint32_t unit, kinc_g4_texture_t *texture) {
|
||||
if (!texture->impl._uploaded) {
|
||||
kinc_g5_command_list_upload_texture(&commandList, &texture->impl._texture);
|
||||
texture->impl._uploaded = true;
|
||||
}
|
||||
|
||||
assert(KINC_G4_SHADER_TYPE_COUNT == KINC_G5_SHADER_TYPE_COUNT);
|
||||
kinc_g5_texture_unit_t g5_unit = {0};
|
||||
for (int i = 0; i < KINC_G5_SHADER_TYPE_COUNT; ++i) {
|
||||
g5_unit.stages[i] = unit;
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
for (int i = 0; i < current_state.texture_count; ++i) {
|
||||
if (kinc_g5_texture_unit_equals(¤t_state.texture_units[i], &g5_unit)) {
|
||||
current_state.textures[i] = &texture->impl._texture;
|
||||
current_state.texture_units[i] = g5_unit;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
assert(current_state.texture_count < MAX_TEXTURES);
|
||||
current_state.textures[current_state.texture_count] = &texture->impl._texture;
|
||||
current_state.texture_units[current_state.texture_count] = g5_unit;
|
||||
current_state.texture_count += 1;
|
||||
}
|
||||
|
||||
kinc_g5_command_list_set_texture(&commandList, g5_unit, &texture->impl._texture);
|
||||
}
|
||||
#else
|
||||
void kinc_g4_set_texture(kinc_g4_texture_unit_t unit, kinc_g4_texture_t *texture) {
|
||||
if (!texture->impl._uploaded) {
|
||||
kinc_g5_command_list_upload_texture(&commandList, &texture->impl._texture);
|
||||
texture->impl._uploaded = true;
|
||||
}
|
||||
|
||||
assert(KINC_G4_SHADER_TYPE_COUNT == KINC_G5_SHADER_TYPE_COUNT);
|
||||
kinc_g5_texture_unit_t g5_unit;
|
||||
memcpy(&g5_unit.stages[0], &unit.stages[0], KINC_G5_SHADER_TYPE_COUNT * sizeof(int));
|
||||
|
||||
bool found = false;
|
||||
for (int i = 0; i < current_state.texture_count; ++i) {
|
||||
if (kinc_g5_texture_unit_equals(¤t_state.texture_units[i], &g5_unit)) {
|
||||
current_state.textures[i] = &texture->impl._texture;
|
||||
current_state.texture_units[i] = g5_unit;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
assert(current_state.texture_count < MAX_TEXTURES);
|
||||
current_state.textures[current_state.texture_count] = &texture->impl._texture;
|
||||
current_state.texture_units[current_state.texture_count] = g5_unit;
|
||||
current_state.texture_count += 1;
|
||||
}
|
||||
|
||||
kinc_g5_command_list_set_texture(&commandList, g5_unit, &texture->impl._texture);
|
||||
}
|
||||
#endif
|
||||
|
||||
void kinc_g4_set_image_texture(kinc_g4_texture_unit_t unit, kinc_g4_texture_t *texture) {}
|
||||
|
||||
int kinc_g4_max_bound_textures(void) {
|
||||
return kinc_g5_max_bound_textures();
|
||||
}
|
||||
|
||||
bool kinc_g4_init_occlusion_query(unsigned *occlusionQuery) {
|
||||
return kinc_g5_command_list_init_occlusion_query(&commandList, occlusionQuery);
|
||||
}
|
||||
|
||||
void kinc_g4_delete_occlusion_query(unsigned occlusionQuery) {
|
||||
kinc_g5_command_list_delete_occlusion_query(&commandList, occlusionQuery);
|
||||
}
|
||||
|
||||
bool kinc_g4_are_query_results_available(unsigned occlusionQuery) {
|
||||
return kinc_g5_command_list_are_query_results_available(&commandList, occlusionQuery);
|
||||
}
|
||||
|
||||
void kinc_g4_get_query_result(unsigned occlusionQuery, unsigned *pixelCount) {
|
||||
kinc_g5_command_list_get_query_result(&commandList, occlusionQuery, pixelCount);
|
||||
}
|
||||
|
||||
void kinc_g4_set_pipeline(kinc_g4_pipeline_t *pipeline) {
|
||||
kinc_g5_pipeline_t *g5_pipeline = &pipeline->impl._pipeline;
|
||||
current_state.pipeline = g5_pipeline;
|
||||
kinc_g5_command_list_set_pipeline(&commandList, g5_pipeline);
|
||||
}
|
||||
|
||||
void kinc_g4_set_blend_constant(float r, float g, float b, float a) {
|
||||
current_state.blend_constant_set = true;
|
||||
current_state.blend_constant_r = r;
|
||||
current_state.blend_constant_g = g;
|
||||
current_state.blend_constant_b = b;
|
||||
current_state.blend_constant_a = a;
|
||||
kinc_g5_command_list_set_blend_constant(&commandList, r, g, b, a);
|
||||
}
|
||||
|
||||
void kinc_g4_set_texture_array(kinc_g4_texture_unit_t unit, struct kinc_g4_texture_array *array) {}
|
||||
|
||||
bool kinc_g4_supports_instanced_rendering(void) {
|
||||
return kinc_g5_supports_instanced_rendering();
|
||||
}
|
||||
|
||||
bool kinc_g4_supports_compute_shaders(void) {
|
||||
return kinc_g5_supports_compute_shaders();
|
||||
}
|
||||
|
||||
bool kinc_g4_supports_blend_constants(void) {
|
||||
return kinc_g5_supports_blend_constants();
|
||||
}
|
||||
|
||||
bool kinc_g4_supports_non_pow2_textures(void) {
|
||||
return kinc_g5_supports_non_pow2_textures();
|
||||
}
|
||||
|
||||
bool kinc_g4_render_targets_inverted_y(void) {
|
||||
return kinc_g5_render_targets_inverted_y();
|
||||
}
|
||||
|
||||
#ifdef KINC_KONG
|
||||
void kinc_g4_render_target_use_color_as_texture(kinc_g4_render_target_t *render_target, uint32_t unit) {
|
||||
if (render_target->impl.state != KINC_INTERNAL_RENDER_TARGET_STATE_TEXTURE) {
|
||||
kinc_g5_command_list_render_target_to_texture_barrier(&commandList, &render_target->impl._renderTarget);
|
||||
render_target->impl.state = KINC_INTERNAL_RENDER_TARGET_STATE_TEXTURE;
|
||||
}
|
||||
|
||||
assert(KINC_G4_SHADER_TYPE_COUNT == KINC_G5_SHADER_TYPE_COUNT);
|
||||
kinc_g5_texture_unit_t g5_unit = {0};
|
||||
for (int i = 0; i < KINC_G5_SHADER_TYPE_COUNT; ++i) {
|
||||
g5_unit.stages[i] = unit;
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
for (int i = 0; i < current_state.render_target_count; ++i) {
|
||||
if (kinc_g5_texture_unit_equals(¤t_state.render_target_units[i], &g5_unit)) {
|
||||
current_state.render_targets[i] = &render_target->impl._renderTarget;
|
||||
current_state.render_target_units[i] = g5_unit;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
assert(current_state.render_target_count < MAX_TEXTURES);
|
||||
current_state.render_targets[current_state.render_target_count] = &render_target->impl._renderTarget;
|
||||
current_state.render_target_units[current_state.render_target_count] = g5_unit;
|
||||
current_state.render_target_count += 1;
|
||||
}
|
||||
|
||||
kinc_g5_command_list_set_texture_from_render_target(&commandList, g5_unit, &render_target->impl._renderTarget);
|
||||
}
|
||||
#else
|
||||
void kinc_g4_render_target_use_color_as_texture(kinc_g4_render_target_t *render_target, kinc_g4_texture_unit_t unit) {
|
||||
if (render_target->impl.state != KINC_INTERNAL_RENDER_TARGET_STATE_TEXTURE) {
|
||||
kinc_g5_command_list_render_target_to_texture_barrier(&commandList, &render_target->impl._renderTarget);
|
||||
render_target->impl.state = KINC_INTERNAL_RENDER_TARGET_STATE_TEXTURE;
|
||||
}
|
||||
|
||||
assert(KINC_G4_SHADER_TYPE_COUNT == KINC_G5_SHADER_TYPE_COUNT);
|
||||
kinc_g5_texture_unit_t g5_unit;
|
||||
memcpy(&g5_unit.stages[0], &unit.stages[0], KINC_G5_SHADER_TYPE_COUNT * sizeof(int));
|
||||
|
||||
bool found = false;
|
||||
for (int i = 0; i < current_state.render_target_count; ++i) {
|
||||
if (kinc_g5_texture_unit_equals(¤t_state.render_target_units[i], &g5_unit)) {
|
||||
current_state.render_targets[i] = &render_target->impl._renderTarget;
|
||||
current_state.render_target_units[i] = g5_unit;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
assert(current_state.render_target_count < MAX_TEXTURES);
|
||||
current_state.render_targets[current_state.render_target_count] = &render_target->impl._renderTarget;
|
||||
current_state.render_target_units[current_state.render_target_count] = g5_unit;
|
||||
current_state.render_target_count += 1;
|
||||
}
|
||||
|
||||
kinc_g5_command_list_set_texture_from_render_target(&commandList, g5_unit, &render_target->impl._renderTarget);
|
||||
}
|
||||
#endif
|
||||
|
||||
void kinc_g4_render_target_use_depth_as_texture(kinc_g4_render_target_t *render_target, kinc_g4_texture_unit_t unit) {
|
||||
if (render_target->impl.state != KINC_INTERNAL_RENDER_TARGET_STATE_TEXTURE) {
|
||||
kinc_g5_command_list_render_target_to_texture_barrier(&commandList, &render_target->impl._renderTarget);
|
||||
render_target->impl.state = KINC_INTERNAL_RENDER_TARGET_STATE_TEXTURE;
|
||||
}
|
||||
|
||||
assert(KINC_G4_SHADER_TYPE_COUNT == KINC_G5_SHADER_TYPE_COUNT);
|
||||
kinc_g5_texture_unit_t g5_unit;
|
||||
memcpy(&g5_unit.stages[0], &unit.stages[0], KINC_G5_SHADER_TYPE_COUNT * sizeof(int));
|
||||
|
||||
bool found = false;
|
||||
for (int i = 0; i < current_state.depth_render_target_count; ++i) {
|
||||
if (kinc_g5_texture_unit_equals(¤t_state.depth_render_target_units[i], &g5_unit)) {
|
||||
current_state.depth_render_targets[i] = &render_target->impl._renderTarget;
|
||||
current_state.depth_render_target_units[i] = g5_unit;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
assert(current_state.depth_render_target_count < MAX_TEXTURES);
|
||||
current_state.depth_render_targets[current_state.depth_render_target_count] = &render_target->impl._renderTarget;
|
||||
current_state.depth_render_target_units[current_state.depth_render_target_count] = g5_unit;
|
||||
current_state.depth_render_target_count += 1;
|
||||
}
|
||||
|
||||
kinc_g5_command_list_set_texture_from_render_target_depth(&commandList, g5_unit, &render_target->impl._renderTarget);
|
||||
}
|
||||
|
||||
#ifdef KINC_KONG
|
||||
void kinc_g4_set_constant_buffer(uint32_t id, struct kinc_g4_constant_buffer *buffer) {
|
||||
kinc_g5_command_list_set_vertex_constant_buffer(&commandList, &buffer->impl.buffer, 0, kinc_g5_constant_buffer_size(&buffer->impl.buffer));
|
||||
}
|
||||
#endif
|
@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/graphics4/graphics.h>
|
||||
#include <kinc/math/matrix.h>
|
@ -0,0 +1,35 @@
|
||||
#ifdef KINC_KONG
|
||||
|
||||
#include <kinc/graphics4/constantbuffer.h>
|
||||
|
||||
void kinc_g4_constant_buffer_init(kinc_g4_constant_buffer *buffer, size_t size) {
|
||||
kinc_g5_constant_buffer_init(&buffer->impl.buffer, (int)size);
|
||||
}
|
||||
|
||||
void kinc_g4_constant_buffer_destroy(kinc_g4_constant_buffer *buffer) {
|
||||
kinc_g5_constant_buffer_destroy(&buffer->impl.buffer);
|
||||
}
|
||||
|
||||
uint8_t *kinc_g4_constant_buffer_lock_all(kinc_g4_constant_buffer *buffer) {
|
||||
kinc_g5_constant_buffer_lock_all(&buffer->impl.buffer);
|
||||
return buffer->impl.buffer.data;
|
||||
}
|
||||
|
||||
uint8_t *kinc_g4_constant_buffer_lock(kinc_g4_constant_buffer *buffer, size_t start, size_t size) {
|
||||
kinc_g5_constant_buffer_lock(&buffer->impl.buffer, (int)start, (int)size);
|
||||
return buffer->impl.buffer.data;
|
||||
}
|
||||
|
||||
void kinc_g4_constant_buffer_unlock_all(kinc_g4_constant_buffer *buffer) {
|
||||
kinc_g5_constant_buffer_unlock(&buffer->impl.buffer);
|
||||
}
|
||||
|
||||
void kinc_g4_constant_buffer_unlock(kinc_g4_constant_buffer *buffer, size_t count) {
|
||||
kinc_g5_constant_buffer_unlock(&buffer->impl.buffer);
|
||||
}
|
||||
|
||||
size_t kinc_g4_constant_buffer_size(kinc_g4_constant_buffer *buffer) {
|
||||
return kinc_g5_constant_buffer_size(&buffer->impl.buffer);
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef KINC_KONG
|
||||
|
||||
#include <kinc/graphics5/constantbuffer.h>
|
||||
|
||||
typedef struct kinc_g4_constant_buffer_impl {
|
||||
kinc_g5_constant_buffer_t buffer;
|
||||
} kinc_g4_constant_buffer_impl;
|
||||
|
||||
#endif
|
@ -0,0 +1,11 @@
|
||||
#include "samplers.c.h"
|
||||
|
||||
#include "G4.c.h"
|
||||
#include "constantbuffer.c.h"
|
||||
#include "indexbuffer.c.h"
|
||||
#include "pipeline.c.h"
|
||||
#include "rendertarget.c.h"
|
||||
#include "shader.c.h"
|
||||
#include "texture.c.h"
|
||||
#include "texturearray.c.h"
|
||||
#include "vertexbuffer.c.h"
|
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "IndexBufferImpl.h"
|
||||
#include "RenderTargetImpl.h"
|
||||
#include "TextureImpl.h"
|
||||
#include "VertexBufferImpl.h"
|
@ -0,0 +1,35 @@
|
||||
#include <kinc/graphics4/indexbuffer.h>
|
||||
|
||||
#include <kinc/graphics5/commandlist.h>
|
||||
|
||||
extern kinc_g5_command_list_t commandList;
|
||||
|
||||
void kinc_g4_index_buffer_init(kinc_g4_index_buffer_t *buffer, int count, kinc_g4_index_buffer_format_t format, kinc_g4_usage_t usage) {
|
||||
kinc_g5_index_buffer_init(&buffer->impl._buffer, count, (kinc_g5_index_buffer_format_t)format, usage == KINC_G4_USAGE_STATIC);
|
||||
}
|
||||
|
||||
void kinc_g4_index_buffer_destroy(kinc_g4_index_buffer_t *buffer) {
|
||||
kinc_g5_index_buffer_destroy(&buffer->impl._buffer);
|
||||
}
|
||||
|
||||
void *kinc_g4_index_buffer_lock_all(kinc_g4_index_buffer_t *buffer) {
|
||||
return kinc_g5_index_buffer_lock_all(&buffer->impl._buffer);
|
||||
}
|
||||
|
||||
void *kinc_g4_index_buffer_lock(kinc_g4_index_buffer_t *buffer, int start, int count) {
|
||||
return kinc_g5_index_buffer_lock(&buffer->impl._buffer, start, count);
|
||||
}
|
||||
|
||||
void kinc_g4_index_buffer_unlock_all(kinc_g4_index_buffer_t *buffer) {
|
||||
kinc_g5_index_buffer_unlock_all(&buffer->impl._buffer);
|
||||
kinc_g5_command_list_upload_index_buffer(&commandList, &buffer->impl._buffer);
|
||||
}
|
||||
|
||||
void kinc_g4_index_buffer_unlock(kinc_g4_index_buffer_t *buffer, int count) {
|
||||
kinc_g5_index_buffer_unlock(&buffer->impl._buffer, count);
|
||||
kinc_g5_command_list_upload_index_buffer(&commandList, &buffer->impl._buffer);
|
||||
}
|
||||
|
||||
int kinc_g4_index_buffer_count(kinc_g4_index_buffer_t *buffer) {
|
||||
return kinc_g5_index_buffer_count(&buffer->impl._buffer);
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/graphics5/indexbuffer.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
kinc_g5_index_buffer_t _buffer;
|
||||
} kinc_g4_index_buffer_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,64 @@
|
||||
#include <kinc/backend/graphics4/pipeline.h>
|
||||
|
||||
#include <kinc/graphics4/pipeline.h>
|
||||
#include <kinc/graphics4/shader.h>
|
||||
#include <kinc/graphics5/pipeline.h>
|
||||
|
||||
void kinc_g4_pipeline_init(kinc_g4_pipeline_t *pipe) {
|
||||
kinc_g4_internal_pipeline_set_defaults(pipe);
|
||||
kinc_g5_pipeline_init(&pipe->impl._pipeline);
|
||||
}
|
||||
|
||||
void kinc_g4_pipeline_destroy(kinc_g4_pipeline_t *pipe) {
|
||||
kinc_g5_pipeline_destroy(&pipe->impl._pipeline);
|
||||
}
|
||||
|
||||
#ifndef KINC_KONG
|
||||
kinc_g4_constant_location_t kinc_g4_pipeline_get_constant_location(kinc_g4_pipeline_t *pipe, const char *name) {
|
||||
kinc_g4_constant_location_t location;
|
||||
location.impl._location = kinc_g5_pipeline_get_constant_location(&pipe->impl._pipeline, name);
|
||||
return location;
|
||||
}
|
||||
|
||||
kinc_g4_texture_unit_t kinc_g4_pipeline_get_texture_unit(kinc_g4_pipeline_t *pipe, const char *name) {
|
||||
kinc_g5_texture_unit_t g5_unit = kinc_g5_pipeline_get_texture_unit(&pipe->impl._pipeline, name);
|
||||
|
||||
assert(KINC_G4_SHADER_TYPE_COUNT == KINC_G5_SHADER_TYPE_COUNT);
|
||||
kinc_g4_texture_unit_t g4_unit;
|
||||
memcpy(&g4_unit.stages[0], &g5_unit.stages[0], KINC_G4_SHADER_TYPE_COUNT * sizeof(int));
|
||||
|
||||
return g4_unit;
|
||||
}
|
||||
#endif
|
||||
|
||||
void kinc_g4_pipeline_compile(kinc_g4_pipeline_t *pipe) {
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
pipe->impl._pipeline.inputLayout[i] = pipe->input_layout[i];
|
||||
}
|
||||
pipe->impl._pipeline.vertexShader = &pipe->vertex_shader->impl._shader;
|
||||
pipe->impl._pipeline.fragmentShader = &pipe->fragment_shader->impl._shader;
|
||||
pipe->impl._pipeline.geometryShader = pipe->geometry_shader != NULL ? &pipe->geometry_shader->impl._shader : NULL;
|
||||
pipe->impl._pipeline.tessellationControlShader = pipe->tessellation_control_shader != NULL ? &pipe->tessellation_control_shader->impl._shader : NULL;
|
||||
pipe->impl._pipeline.tessellationEvaluationShader =
|
||||
pipe->tessellation_evaluation_shader != NULL ? &pipe->tessellation_evaluation_shader->impl._shader : NULL;
|
||||
pipe->impl._pipeline.blend_source = (kinc_g5_blending_factor_t)pipe->blend_source;
|
||||
pipe->impl._pipeline.blend_destination = (kinc_g5_blending_factor_t)pipe->blend_destination;
|
||||
pipe->impl._pipeline.blend_operation = (kinc_g5_blending_operation_t)pipe->blend_operation;
|
||||
pipe->impl._pipeline.alpha_blend_source = (kinc_g5_blending_factor_t)pipe->alpha_blend_source;
|
||||
pipe->impl._pipeline.alpha_blend_destination = (kinc_g5_blending_factor_t)pipe->alpha_blend_destination;
|
||||
pipe->impl._pipeline.alpha_blend_operation = (kinc_g5_blending_operation_t)pipe->alpha_blend_operation;
|
||||
pipe->impl._pipeline.cullMode = (kinc_g5_cull_mode_t)pipe->cull_mode;
|
||||
pipe->impl._pipeline.depthMode = (kinc_g5_compare_mode_t)pipe->depth_mode;
|
||||
pipe->impl._pipeline.depthWrite = pipe->depth_write;
|
||||
pipe->impl._pipeline.colorAttachmentCount = pipe->color_attachment_count;
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
pipe->impl._pipeline.colorWriteMaskRed[i] = pipe->color_write_mask_red[i];
|
||||
pipe->impl._pipeline.colorWriteMaskGreen[i] = pipe->color_write_mask_green[i];
|
||||
pipe->impl._pipeline.colorWriteMaskBlue[i] = pipe->color_write_mask_blue[i];
|
||||
pipe->impl._pipeline.colorWriteMaskAlpha[i] = pipe->color_write_mask_alpha[i];
|
||||
pipe->impl._pipeline.colorAttachment[i] = (kinc_g5_render_target_format_t)pipe->color_attachment[i];
|
||||
}
|
||||
pipe->impl._pipeline.depthAttachmentBits = pipe->depth_attachment_bits;
|
||||
pipe->impl._pipeline.stencilAttachmentBits = pipe->stencil_attachment_bits;
|
||||
kinc_g5_pipeline_compile(&pipe->impl._pipeline);
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/graphics5/constantlocation.h>
|
||||
#include <kinc/graphics5/pipeline.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
// PipelineStateImpl();
|
||||
kinc_g5_pipeline_t _pipeline;
|
||||
} kinc_g4_pipeline_impl_t;
|
||||
|
||||
typedef struct {
|
||||
kinc_g5_constant_location_t _location;
|
||||
} kinc_g4_constant_location_impl_t;
|
||||
|
||||
typedef struct {
|
||||
int nothing;
|
||||
} Kinc_G4_AttributeLocationImpl;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,36 @@
|
||||
#include <kinc/backend/graphics4/rendertarget.h>
|
||||
|
||||
#include <kinc/graphics4/rendertarget.h>
|
||||
#include <kinc/graphics5/commandlist.h>
|
||||
#include <kinc/log.h>
|
||||
|
||||
extern kinc_g5_command_list_t commandList;
|
||||
|
||||
void kinc_g4_render_target_init_with_multisampling(kinc_g4_render_target_t *render_target, int width, int height, kinc_g4_render_target_format_t format,
|
||||
int depthBufferBits, int stencilBufferBits, int samples_per_pixel) {
|
||||
kinc_g5_render_target_init_with_multisampling(&render_target->impl._renderTarget, width, height, (kinc_g5_render_target_format_t)format, depthBufferBits,
|
||||
stencilBufferBits, samples_per_pixel);
|
||||
render_target->texWidth = render_target->width = width;
|
||||
render_target->texHeight = render_target->height = height;
|
||||
render_target->impl.state = KINC_INTERNAL_RENDER_TARGET_STATE_RENDER_TARGET;
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_init_cube_with_multisampling(kinc_g4_render_target_t *render_target, int cubeMapSize, kinc_g4_render_target_format_t format,
|
||||
int depthBufferBits, int stencilBufferBits, int samples_per_pixel) {
|
||||
kinc_g5_render_target_init_cube_with_multisampling(&render_target->impl._renderTarget, cubeMapSize, (kinc_g5_render_target_format_t)format, depthBufferBits,
|
||||
stencilBufferBits, samples_per_pixel);
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_destroy(kinc_g4_render_target_t *render_target) {
|
||||
kinc_g5_render_target_destroy(&render_target->impl._renderTarget);
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_set_depth_stencil_from(kinc_g4_render_target_t *render_target, kinc_g4_render_target_t *source) {
|
||||
kinc_g5_render_target_set_depth_stencil_from(&render_target->impl._renderTarget, &source->impl._renderTarget);
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_get_pixels(kinc_g4_render_target_t *render_target, uint8_t *data) {
|
||||
kinc_g5_command_list_get_render_target_pixels(&commandList, &render_target->impl._renderTarget, data);
|
||||
}
|
||||
|
||||
void kinc_g4_render_target_generate_mipmaps(kinc_g4_render_target_t *render_target, int levels) {}
|
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/graphics5/rendertarget.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum kinc_internal_render_target_state { KINC_INTERNAL_RENDER_TARGET_STATE_RENDER_TARGET, KINC_INTERNAL_RENDER_TARGET_STATE_TEXTURE };
|
||||
|
||||
typedef struct {
|
||||
// RenderTargetImpl(int width, int height, int depthBufferBits, bool antialiasing, Graphics5::RenderTargetFormat format, int stencilBufferBits,
|
||||
// int contextId);
|
||||
// RenderTargetImpl(int cubeMapSize, int depthBufferBits, bool antialiasing, Graphics5::RenderTargetFormat format, int stencilBufferBits, int contextId);
|
||||
kinc_g5_render_target_t _renderTarget;
|
||||
enum kinc_internal_render_target_state state;
|
||||
} kinc_g4_render_target_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,50 @@
|
||||
#include <kinc/graphics5/sampler.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#define MAX_SAMPLERS_PER_STAGE 16
|
||||
|
||||
static kinc_g5_sampler_options_t sampler_options[KINC_G5_SHADER_TYPE_COUNT][MAX_SAMPLERS_PER_STAGE];
|
||||
|
||||
static void samplers_reset(void) {
|
||||
for (int i = 0; i < KINC_G5_SHADER_TYPE_COUNT; ++i) {
|
||||
for (int j = 0; j < MAX_SAMPLERS_PER_STAGE; ++j) {
|
||||
kinc_g5_sampler_options_set_defaults(&sampler_options[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool sampler_options_equals(kinc_g5_sampler_options_t *options1, kinc_g5_sampler_options_t *options2) {
|
||||
return options1->u_addressing == options2->u_addressing && options1->v_addressing == options2->v_addressing &&
|
||||
options1->w_addressing == options2->w_addressing && options1->minification_filter == options2->minification_filter &&
|
||||
options1->magnification_filter == options2->magnification_filter && options1->mipmap_filter == options2->mipmap_filter &&
|
||||
options1->lod_min_clamp == options2->lod_min_clamp && options1->lod_max_clamp == options2->lod_max_clamp &&
|
||||
options1->max_anisotropy == options2->max_anisotropy && options1->is_comparison == options2->is_comparison &&
|
||||
options1->compare_mode == options2->compare_mode;
|
||||
}
|
||||
|
||||
struct sampler_cache_entry {
|
||||
kinc_g5_sampler_options_t options;
|
||||
kinc_g5_sampler_t sampler;
|
||||
};
|
||||
|
||||
#define MAX_SAMPLER_CACHE_SIZE 256
|
||||
static struct sampler_cache_entry sampler_cache[MAX_SAMPLER_CACHE_SIZE];
|
||||
static int sampler_cache_size = 0;
|
||||
|
||||
// TODO: Please make this much faster
|
||||
static kinc_g5_sampler_t *get_current_sampler(int stage, int unit) {
|
||||
for (int i = 0; i < sampler_cache_size; ++i) {
|
||||
if (sampler_options_equals(&sampler_cache[i].options, &sampler_options[stage][unit])) {
|
||||
return &sampler_cache[i].sampler;
|
||||
}
|
||||
}
|
||||
|
||||
assert(sampler_cache_size < MAX_SAMPLER_CACHE_SIZE);
|
||||
kinc_g5_sampler_t *sampler = &sampler_cache[sampler_cache_size].sampler;
|
||||
kinc_g5_sampler_init(sampler, &sampler_options[stage][unit]);
|
||||
sampler_cache[sampler_cache_size].options = sampler_options[stage][unit];
|
||||
sampler_cache_size += 1;
|
||||
|
||||
return sampler;
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
#include <kinc/graphics4/shader.h>
|
||||
|
||||
void kinc_g4_shader_init(kinc_g4_shader_t *shader, const void *_data, size_t length, kinc_g4_shader_type_t type) {
|
||||
kinc_g5_shader_init(&shader->impl._shader, _data, length, (kinc_g5_shader_type_t)type);
|
||||
}
|
||||
|
||||
#ifdef KRAFIX_LIBRARY
|
||||
extern int krafix_compile(const char *source, char *output, int *length, const char *targetlang, const char *system, const char *shadertype, int version);
|
||||
#endif
|
||||
|
||||
int kinc_g4_shader_init_from_source(kinc_g4_shader_t *shader, const char *source, kinc_g4_shader_type_t type) {
|
||||
#ifdef KRAFIX_LIBRARY
|
||||
char *output = malloc(1024 * 1024);
|
||||
int length;
|
||||
|
||||
#ifdef KINC_WINDOWS
|
||||
const char *system = "windows";
|
||||
#elif defined(KINC_MACOS)
|
||||
const char *system = "macos";
|
||||
#elif defined(KINC_LINUX)
|
||||
const char *system = "linux";
|
||||
#elif defined(KINC_ANDROID)
|
||||
const char *system = "android";
|
||||
#elif defined(KINC_IOS)
|
||||
const char *system = "ios";
|
||||
#endif
|
||||
|
||||
#ifdef KORE_VULKAN
|
||||
const char *target = "spirv";
|
||||
#elif defined(KORE_METAL)
|
||||
const char *target = "metal";
|
||||
#else
|
||||
const char *target = "d3d11";
|
||||
#endif
|
||||
|
||||
int errors = krafix_compile(source, output, &length, target, system, type == KINC_G4_SHADER_TYPE_FRAGMENT ? "frag" : "vert", -1);
|
||||
if (errors > 0) {
|
||||
return errors;
|
||||
}
|
||||
kinc_g4_shader_init(shader, output, length, type);
|
||||
return 0;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void kinc_g4_shader_destroy(kinc_g4_shader_t *shader) {
|
||||
kinc_g5_shader_destroy(&shader->impl._shader);
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/graphics5/shader.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
// ShaderImpl(void *data, int length, Graphics5::ShaderType type);
|
||||
kinc_g5_shader_t _shader;
|
||||
} kinc_g4_shader_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,70 @@
|
||||
#include <kinc/graphics4/graphics.h>
|
||||
#include <kinc/graphics4/texture.h>
|
||||
#include <kinc/graphics5/texture.h>
|
||||
#include <kinc/io/filereader.h>
|
||||
|
||||
#include <kinc/backend/graphics4/texture.h>
|
||||
|
||||
void kinc_g4_texture_init_from_image(kinc_g4_texture_t *texture, kinc_image_t *image) {
|
||||
texture->impl._uploaded = false;
|
||||
kinc_g5_texture_init_from_image(&texture->impl._texture, image);
|
||||
texture->tex_width = texture->impl._texture.texWidth;
|
||||
texture->tex_height = texture->impl._texture.texHeight;
|
||||
texture->tex_depth = 1;
|
||||
texture->format = image->format;
|
||||
}
|
||||
|
||||
void kinc_g4_texture_init_from_image3d(kinc_g4_texture_t *texture, kinc_image_t *image) {}
|
||||
|
||||
void kinc_g4_texture_init(kinc_g4_texture_t *texture, int width, int height, kinc_image_format_t format) {
|
||||
texture->impl._uploaded = true;
|
||||
kinc_g5_texture_init(&texture->impl._texture, width, height, format);
|
||||
texture->tex_width = texture->impl._texture.texWidth;
|
||||
texture->tex_height = texture->impl._texture.texHeight;
|
||||
texture->tex_depth = 1;
|
||||
texture->format = format;
|
||||
}
|
||||
|
||||
void kinc_g4_texture_init3d(kinc_g4_texture_t *texture, int width, int height, int depth, kinc_image_format_t format) {}
|
||||
|
||||
void kinc_g4_texture_init_from_bytes(kinc_g4_texture_t *texture, void *data, int size, const char *format) {}
|
||||
|
||||
void kinc_g4_texture_init_from_bytes3d(kinc_g4_texture_t *texture, void *data, int width, int height, int depth, int format, bool readable) {}
|
||||
|
||||
void kinc_g4_texture_destroy(kinc_g4_texture_t *texture) {
|
||||
// kinc_g4_internal_texture_unset(texture);
|
||||
kinc_g5_texture_destroy(&texture->impl._texture);
|
||||
}
|
||||
|
||||
void kinc_g4_internal_texture_unset(kinc_g4_texture_t *texture) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void kinc_g4_internal_texture_unmipmap(kinc_g4_texture_t *texture) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
uint8_t *kinc_g4_texture_lock(kinc_g4_texture_t *texture) {
|
||||
return kinc_g5_texture_lock(&texture->impl._texture);
|
||||
}
|
||||
|
||||
void kinc_g4_texture_unlock(kinc_g4_texture_t *texture) {
|
||||
kinc_g5_texture_unlock(&texture->impl._texture);
|
||||
texture->impl._uploaded = false;
|
||||
}
|
||||
|
||||
void kinc_g4_texture_clear(kinc_g4_texture_t *texture, int x, int y, int z, int width, int height, int depth, unsigned color) {
|
||||
kinc_g5_texture_clear(&texture->impl._texture, x, y, z, width, height, depth, color);
|
||||
}
|
||||
|
||||
int kinc_g4_texture_stride(kinc_g4_texture_t *texture) {
|
||||
return kinc_g5_texture_stride(&texture->impl._texture);
|
||||
}
|
||||
|
||||
void kinc_g4_texture_generate_mipmaps(kinc_g4_texture_t *texture, int levels) {
|
||||
kinc_g5_texture_generate_mipmaps(&texture->impl._texture, levels);
|
||||
}
|
||||
|
||||
void kinc_g4_texture_set_mipmap(kinc_g4_texture_t *texture, kinc_image_t *mipmap, int level) {
|
||||
kinc_g5_texture_set_mipmap(&texture->impl._texture, mipmap, level);
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/graphics5/texture.h>
|
||||
#include <kinc/graphics5/textureunit.h>
|
||||
#include <kinc/image.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
kinc_g5_texture_unit_t _unit;
|
||||
} kinc_g4_texture_unit_impl_t;
|
||||
|
||||
typedef struct {
|
||||
/*TextureImpl();
|
||||
TextureImpl(int width, int height, Image::Format format, bool readable);
|
||||
TextureImpl(int width, int height, int depth, Image::Format format, bool readable);
|
||||
~TextureImpl();
|
||||
void unmipmap();
|
||||
void unset();*/
|
||||
|
||||
kinc_g5_texture_t _texture;
|
||||
bool _uploaded;
|
||||
} kinc_g4_texture_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -0,0 +1,7 @@
|
||||
#include <kinc/graphics4/texturearray.h>
|
||||
|
||||
void kinc_g4_texture_array_init(kinc_g4_texture_array_t *array, kinc_image_t *textures, int count) {}
|
||||
|
||||
void kinc_g4_texture_array_destroy(kinc_g4_texture_array_t *array) {}
|
||||
|
||||
// void TextureArrayImpl::set(TextureUnit unit) {}
|
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
// void set(Kore::Graphics4::TextureUnit unit);
|
||||
int nothing;
|
||||
} kinc_g4_texture_array_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user