Add files
This commit is contained in:
@ -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
|
@ -0,0 +1,64 @@
|
||||
#include <kinc/backend/graphics4/vertexbuffer.h>
|
||||
|
||||
#include <kinc/graphics4/graphics.h>
|
||||
#include <kinc/graphics4/vertexbuffer.h>
|
||||
|
||||
extern uint64_t frameNumber;
|
||||
extern bool waitAfterNextDraw;
|
||||
|
||||
void kinc_g4_vertex_buffer_init(kinc_g4_vertex_buffer_t *buffer, int count, kinc_g4_vertex_structure_t *structure, kinc_g4_usage_t usage,
|
||||
int instanceDataStepRate) {
|
||||
int multiple = usage == KINC_G4_USAGE_STATIC ? 1 : 500;
|
||||
kinc_g5_vertex_buffer_init(&buffer->impl._buffer, count * multiple, structure, usage == KINC_G4_USAGE_STATIC, instanceDataStepRate);
|
||||
buffer->impl._multiple = multiple;
|
||||
buffer->impl._lastFrameNumber = 0;
|
||||
buffer->impl._currentIndex = 0;
|
||||
buffer->impl.myCount = count;
|
||||
}
|
||||
|
||||
void kinc_g4_vertex_buffer_destroy(kinc_g4_vertex_buffer_t *buffer) {
|
||||
kinc_g5_vertex_buffer_destroy(&buffer->impl._buffer);
|
||||
}
|
||||
|
||||
static void prepareLock(kinc_g4_vertex_buffer_t *buffer) {
|
||||
/*if (frameNumber > _lastFrameNumber) {
|
||||
_lastFrameNumber = frameNumber;
|
||||
_currentIndex = 0;
|
||||
}
|
||||
else {*/
|
||||
++buffer->impl._currentIndex;
|
||||
if (buffer->impl._currentIndex >= buffer->impl._multiple - 1) {
|
||||
waitAfterNextDraw = true;
|
||||
}
|
||||
if (buffer->impl._currentIndex >= buffer->impl._multiple) {
|
||||
buffer->impl._currentIndex = 0;
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
float *kinc_g4_vertex_buffer_lock_all(kinc_g4_vertex_buffer_t *buffer) {
|
||||
prepareLock(buffer);
|
||||
return kinc_g5_vertex_buffer_lock(&buffer->impl._buffer, buffer->impl._currentIndex * kinc_g4_vertex_buffer_count(buffer),
|
||||
kinc_g4_vertex_buffer_count(buffer));
|
||||
}
|
||||
|
||||
float *kinc_g4_vertex_buffer_lock(kinc_g4_vertex_buffer_t *buffer, int start, int count) {
|
||||
prepareLock(buffer);
|
||||
return kinc_g5_vertex_buffer_lock(&buffer->impl._buffer, start + buffer->impl._currentIndex * kinc_g4_vertex_buffer_count(buffer), count);
|
||||
}
|
||||
|
||||
void kinc_g4_vertex_buffer_unlock_all(kinc_g4_vertex_buffer_t *buffer) {
|
||||
kinc_g5_vertex_buffer_unlock_all(&buffer->impl._buffer);
|
||||
}
|
||||
|
||||
void kinc_g4_vertex_buffer_unlock(kinc_g4_vertex_buffer_t *buffer, int count) {
|
||||
kinc_g5_vertex_buffer_unlock(&buffer->impl._buffer, count);
|
||||
}
|
||||
|
||||
int kinc_g4_vertex_buffer_count(kinc_g4_vertex_buffer_t *buffer) {
|
||||
return buffer->impl.myCount;
|
||||
}
|
||||
|
||||
int kinc_g4_vertex_buffer_stride(kinc_g4_vertex_buffer_t *buffer) {
|
||||
return kinc_g5_vertex_buffer_stride(&buffer->impl._buffer);
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <kinc/graphics5/vertexbuffer.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
int myCount;
|
||||
// void prepareLock();
|
||||
kinc_g5_vertex_buffer_t _buffer;
|
||||
int _currentIndex;
|
||||
int _multiple;
|
||||
uint64_t _lastFrameNumber;
|
||||
} kinc_g4_vertex_buffer_impl_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
2
Kinc/Backends/Graphics4/OpenGL/Sources/GL/.clang-format
Normal file
2
Kinc/Backends/Graphics4/OpenGL/Sources/GL/.clang-format
Normal file
@ -0,0 +1,2 @@
|
||||
DisableFormat: true
|
||||
SortIncludes: false
|
2261
Kinc/Backends/Graphics4/OpenGL/Sources/GL/eglew.h
Normal file
2261
Kinc/Backends/Graphics4/OpenGL/Sources/GL/eglew.h
Normal file
File diff suppressed because it is too large
Load Diff
23955
Kinc/Backends/Graphics4/OpenGL/Sources/GL/glew.c
Normal file
23955
Kinc/Backends/Graphics4/OpenGL/Sources/GL/glew.c
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user