diff --git a/.gitmodules b/.gitmodules index a36ddbc11..75c54166d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,14 +1,14 @@ [submodule "Tools/kraffiti"] path = Tools/kraffiti url = https://github.com/Kode/kraffiti_bin.git - branch = master + branch = jscompat shallow = true [submodule "Tools/krafix"] path = Tools/krafix url = https://github.com/Kode/krafix_bin.git - branch = master + branch = jscompat shallow = true [submodule "Tools/kincmake"] path = Tools/kincmake url = https://github.com/Kode/kincmake.git - branch = master + branch = jscompat diff --git a/Backends/Audio2/WASAPI/Sources/Kore/WASAPI.winrt.cpp b/Backends/Audio2/WASAPI/Sources/Kore/WASAPI.winrt.cpp index 3bb004dd9..b7ca902fc 100644 --- a/Backends/Audio2/WASAPI/Sources/Kore/WASAPI.winrt.cpp +++ b/Backends/Audio2/WASAPI/Sources/Kore/WASAPI.winrt.cpp @@ -33,15 +33,87 @@ namespace { IMMDeviceEnumerator *deviceEnumerator; IMMDevice *device; - IAudioClient *audioClient; - IAudioRenderClient *renderClient; - HANDLE bufferEndEvent; + IAudioClient *audioClient = NULL; + IAudioRenderClient *renderClient = NULL; + HANDLE bufferEndEvent = 0; HANDLE audioProcessingDoneEvent; UINT32 bufferFrames; WAVEFORMATEX requestedFormat; WAVEFORMATEX *closestFormat; WAVEFORMATEX *format; + bool initDefaultDevice(void) { + if (renderClient != NULL) { + renderClient->Release(); + renderClient = NULL; + } + + if (audioClient != NULL) { + audioClient->Release(); + audioClient = NULL; + } + + if (bufferEndEvent != 0) { + CloseHandle(bufferEndEvent); + bufferEndEvent = 0; + } + + log(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(&audioClient)); + } + + if (hr == S_OK) { + const int sampleRate = 48000; + + format = &requestedFormat; + ZeroMemory(&requestedFormat, 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) { + log(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) { + log(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(&renderClient))); + + bufferEndEvent = CreateEvent(0, FALSE, FALSE, 0); + 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; @@ -56,9 +128,27 @@ namespace { *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; - if (FAILED(renderClient->GetBuffer(frames, &buffer))) { + HRESULT result = renderClient->GetBuffer(frames, &buffer); + if (FAILED(result)) { + if (result == AUDCLNT_E_DEVICE_INVALIDATED) { + initDefaultDevice(); + submitEmptyBuffer(bufferFrames); + audioClient->Start(); + } return; } @@ -82,7 +172,14 @@ namespace { memset(buffer, 0, frames * format->nBlockAlign); } - renderClient->ReleaseBuffer(frames, 0); + result = renderClient->ReleaseBuffer(frames, 0); + if (FAILED(result)) { + if (result == AUDCLNT_E_DEVICE_INVALIDATED) { + initDefaultDevice(); + submitEmptyBuffer(bufferFrames); + audioClient->Start(); + } + } } void audioThread(LPVOID) { @@ -91,7 +188,13 @@ namespace { while (WAIT_OBJECT_0 != WaitForSingleObject(audioProcessingDoneEvent, 0)) { WaitForSingleObject(bufferEndEvent, INFINITE); UINT32 padding = 0; - if (FAILED(audioClient->GetCurrentPadding(&padding))) { + HRESULT result = audioClient->GetCurrentPadding(&padding); + if (FAILED(result)) { + if (result == AUDCLNT_E_DEVICE_INVALIDATED) { + initDefaultDevice(); + submitEmptyBuffer(bufferFrames); + audioClient->Start(); + } continue; } UINT32 frames = bufferFrames - padding; @@ -99,56 +202,6 @@ namespace { } } - void initAudio() { - const int sampleRate = 48000; - - bufferEndEvent = CreateEvent(0, FALSE, FALSE, 0); - affirm(bufferEndEvent != 0); - - audioProcessingDoneEvent = CreateEvent(0, FALSE, FALSE, 0); - affirm(audioProcessingDoneEvent != 0); - - format = &requestedFormat; - ZeroMemory(&requestedFormat, 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) { - log(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) { - log(Warning, "Could not initialize WASAPI audio, going silent (error code 0x%x).", result); - return; - } - - 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(&renderClient))); - kinc_microsoft_affirm(audioClient->SetEventHandle(bufferEndEvent)); - -#ifdef KORE_WINRT - audioThread(nullptr); -#else - createAndRunThread(audioThread, nullptr); -#endif - } - #ifdef KORE_WINRT class AudioRenderer : public RuntimeClass, FtmBase, IActivateAudioInterfaceCompletionHandler> { public: @@ -192,16 +245,18 @@ void kinc_a2_init() { kinc_microsoft_affirm(CoInitializeEx(0, COINIT_MULTITHREADED)); kinc_microsoft_affirm( CoCreateInstance(__uuidof(MMDeviceEnumerator), 0, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), reinterpret_cast(&deviceEnumerator))); - HRESULT hr = deviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &device); - if (hr == S_OK) { - hr = device->Activate(__uuidof(IAudioClient), CLSCTX_ALL, 0, reinterpret_cast(&audioClient)); - } - if (hr == S_OK) { - initAudio(); - } - else { - kinc_log(KINC_LOG_LEVEL_WARNING, "Could not initialize WASAPI audio."); + + audioProcessingDoneEvent = CreateEvent(0, FALSE, FALSE, 0); + affirm(audioProcessingDoneEvent != 0); + + if (initDefaultDevice()) { +#ifdef KORE_WINRT + audioThread(nullptr); +#else + createAndRunThread(audioThread, nullptr); +#endif } + #else renderer = Make(); diff --git a/Backends/Graphics4/G4onG5/Sources/Kore/PipelineStateImpl.c b/Backends/Graphics4/G4onG5/Sources/Kore/PipelineStateImpl.c index 67709c420..ca19f63fc 100644 --- a/Backends/Graphics4/G4onG5/Sources/Kore/PipelineStateImpl.c +++ b/Backends/Graphics4/G4onG5/Sources/Kore/PipelineStateImpl.c @@ -3,8 +3,8 @@ #include "PipelineStateImpl.h" #include -#include #include +#include void kinc_g4_pipeline_init(kinc_g4_pipeline_t *pipe) { kinc_g4_internal_pipeline_set_defaults(pipe); @@ -35,7 +35,8 @@ void kinc_g4_pipeline_compile(kinc_g4_pipeline_t *pipe) { 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.tessellationEvaluationShader = + pipe->tessellation_evaluation_shader != NULL ? &pipe->tessellation_evaluation_shader->impl._shader : NULL; pipe->impl._pipeline.blendSource = (kinc_g5_blending_operation_t)pipe->blend_source; pipe->impl._pipeline.blendDestination = (kinc_g5_blending_operation_t)pipe->blend_destination; pipe->impl._pipeline.alphaBlendSource = (kinc_g5_blending_operation_t)pipe->alpha_blend_source; @@ -49,7 +50,7 @@ void kinc_g4_pipeline_compile(kinc_g4_pipeline_t *pipe) { 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] = pipe->color_attachment[i]; + pipe->impl._pipeline.colorAttachment[i] = (kinc_g5_render_target_format_t)pipe->color_attachment[i]; } kinc_g5_pipeline_compile(&pipe->impl._pipeline); } diff --git a/Backends/Graphics4/G4onG5/Sources/Kore/RenderTargetImpl.c b/Backends/Graphics4/G4onG5/Sources/Kore/RenderTargetImpl.c index 00ce9d4df..b9c0d88e8 100644 --- a/Backends/Graphics4/G4onG5/Sources/Kore/RenderTargetImpl.c +++ b/Backends/Graphics4/G4onG5/Sources/Kore/RenderTargetImpl.c @@ -9,15 +9,16 @@ extern kinc_g5_command_list_t commandList; void kinc_g4_render_target_init(kinc_g4_render_target_t *render_target, int width, int height, int depthBufferBits, bool antialiasing, - kinc_g4_render_target_format_t format, int stencilBufferBits, - int contextId) { + kinc_g4_render_target_format_t format, int stencilBufferBits, int contextId) { kinc_g5_render_target_init(&render_target->impl._renderTarget, width, height, depthBufferBits, antialiasing, (kinc_g5_render_target_format_t)format, stencilBufferBits, contextId); render_target->texWidth = render_target->width = width; render_target->texHeight = render_target->height = height; if (contextId >= 0) { kinc_g5_command_list_texture_to_render_target_barrier(&commandList, &render_target->impl._renderTarget); +#ifndef KORE_VULKAN kinc_g5_command_list_clear(&commandList, &render_target->impl._renderTarget, KINC_G5_CLEAR_COLOR, 0, 0.0f, 0); +#endif } } @@ -32,7 +33,9 @@ void kinc_g4_render_target_destroy(kinc_g4_render_target_t *render_target) { } void kinc_g4_render_target_use_color_as_texture(kinc_g4_render_target_t *render_target, kinc_g4_texture_unit_t unit) { +#ifndef KORE_VULKAN kinc_g5_command_list_render_target_to_texture_barrier(&commandList, &render_target->impl._renderTarget); +#endif kinc_g5_render_target_use_color_as_texture(&render_target->impl._renderTarget, unit.impl._unit); } diff --git a/Backends/Graphics5/Direct3D12/Sources/Kore/CommandList5Impl.cpp b/Backends/Graphics5/Direct3D12/Sources/Kore/CommandList5Impl.cpp index b0c5375a2..5015f5259 100644 --- a/Backends/Graphics5/Direct3D12/Sources/Kore/CommandList5Impl.cpp +++ b/Backends/Graphics5/Direct3D12/Sources/Kore/CommandList5Impl.cpp @@ -11,7 +11,7 @@ #include -extern ID3D12CommandQueue* commandQueue; +extern ID3D12CommandQueue *commandQueue; namespace { /*const int constantBufferMultiply = 1024; @@ -43,7 +43,7 @@ namespace { }*/ UINT64 renderFenceValue = 0; - ID3D12Fence* renderFence; + ID3D12Fence *renderFence; HANDLE renderFenceEvent; void init() { @@ -55,7 +55,7 @@ namespace { } } - void waitForFence(ID3D12Fence* fence, UINT64 completionValue, HANDLE waitEvent) { + void waitForFence(ID3D12Fence *fence, UINT64 completionValue, HANDLE waitEvent) { if (fence->GetCompletedValue() < completionValue) { fence->SetEventOnCompletion(completionValue, waitEvent); WaitForSingleObject(waitEvent, INFINITE); @@ -77,7 +77,8 @@ namespace { commandAllocator->Reset(); list->impl._commandList->Reset(commandAllocator, nullptr); if (renderTarget != nullptr) { - list->impl._commandList->OMSetRenderTargets(1, &renderTarget->impl.renderTargetDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), true, nullptr); + auto descriptorHandle = renderTarget->impl.renderTargetDescriptorHeap->GetCPUDescriptorHandleForHeapStart(); + list->impl._commandList->OMSetRenderTargets(1, &descriptorHandle, true, nullptr); list->impl._commandList->RSSetViewports(1, (D3D12_VIEWPORT *)&renderTarget->impl.viewport); list->impl._commandList->RSSetScissorRects(1, (D3D12_RECT *)&renderTarget->impl.scissor); } @@ -137,18 +138,17 @@ void kinc_g5_command_list_end(kinc_g5_command_list *list) { void kinc_g5_command_list_clear(kinc_g5_command_list *list, kinc_g5_render_target_t *renderTarget, unsigned flags, unsigned color, float depth, int stencil) { if (flags & KINC_G5_CLEAR_COLOR) { - float clearColor[] = {((color & 0x00ff0000) >> 16) / 255.0f, - ((color & 0x0000ff00) >> 8) / 255.0f, - (color & 0x000000ff) / 255.0f, - ((color & 0xff000000) >> 24) / 255.0f}; - list->impl._commandList->ClearRenderTargetView(renderTarget->impl.renderTargetDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), clearColor, 0, nullptr); + float clearColor[] = {((color & 0x00ff0000) >> 16) / 255.0f, ((color & 0x0000ff00) >> 8) / 255.0f, (color & 0x000000ff) / 255.0f, + ((color & 0xff000000) >> 24) / 255.0f}; + list->impl._commandList->ClearRenderTargetView(renderTarget->impl.renderTargetDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), clearColor, 0, + nullptr); } if ((flags & KINC_G5_CLEAR_DEPTH) || (flags & KINC_G5_CLEAR_STENCIL)) { D3D12_CLEAR_FLAGS d3dflags = (flags & KINC_G5_CLEAR_DEPTH) && (flags & KINC_G5_CLEAR_STENCIL) ? D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL : (flags & KINC_G5_CLEAR_DEPTH) ? D3D12_CLEAR_FLAG_DEPTH : D3D12_CLEAR_FLAG_STENCIL; - list->impl._commandList->ClearDepthStencilView(renderTarget->impl.depthStencilDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), d3dflags, depth, stencil, - 0, nullptr); + list->impl._commandList->ClearDepthStencilView(renderTarget->impl.depthStencilDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), d3dflags, depth, + stencil, 0, nullptr); } } @@ -211,7 +211,7 @@ void kinc_g5_command_list_set_pipeline_layout(kinc_g5_command_list *list) { } void kinc_g5_command_list_set_vertex_constant_buffer(kinc_g5_command_list *list, kinc_g5_constant_buffer_t *buffer, int offset, size_t size) { - #ifdef KORE_DXC +#ifdef KORE_DXC_DISABLED if (list->impl._currentPipeline->impl.vertexConstantsSize > 0) { if (list->impl._currentPipeline->impl.textures > 0) { list->impl._commandList->SetGraphicsRootConstantBufferView(2, buffer->impl.constant_buffer->GetGPUVirtualAddress() + offset); @@ -220,19 +220,19 @@ void kinc_g5_command_list_set_vertex_constant_buffer(kinc_g5_command_list *list, list->impl._commandList->SetGraphicsRootConstantBufferView(0, buffer->impl.constant_buffer->GetGPUVirtualAddress() + offset); } } - #else +#else list->impl._commandList->SetGraphicsRootConstantBufferView(2, buffer->impl.constant_buffer->GetGPUVirtualAddress() + offset); - #endif +#endif } void kinc_g5_command_list_set_fragment_constant_buffer(kinc_g5_command_list *list, kinc_g5_constant_buffer_t *buffer, int offset, size_t size) { - #ifdef KORE_DXC +#ifdef KORE_DXC_DISABLED if (list->impl._currentPipeline->impl.fragmentConstantsSize > 0) { - //list->impl._commandList->SetGraphicsRootConstantBufferView(3, buffer->impl.constant_buffer->GetGPUVirtualAddress() + offset); + // list->impl._commandList->SetGraphicsRootConstantBufferView(3, buffer->impl.constant_buffer->GetGPUVirtualAddress() + offset); } - #else +#else list->impl._commandList->SetGraphicsRootConstantBufferView(3, buffer->impl.constant_buffer->GetGPUVirtualAddress() + offset); - #endif +#endif } void kinc_g5_command_list_draw_indexed_vertices(kinc_g5_command_list *list) { @@ -332,9 +332,13 @@ void kinc_g5_command_list_set_render_targets(kinc_g5_command_list *list, kinc_g5 for (int i = 0; i < count; ++i) { targetDescriptors[i] = targets[i]->impl.renderTargetDescriptorHeap->GetCPUDescriptorHandleForHeapStart(); } - list->impl._commandList->OMSetRenderTargets( - count, &targetDescriptors[0], false, - targets[0]->impl.depthStencilDescriptorHeap != nullptr ? &targets[0]->impl.depthStencilDescriptorHeap->GetCPUDescriptorHandleForHeapStart() : nullptr); + D3D12_CPU_DESCRIPTOR_HANDLE handle; + D3D12_CPU_DESCRIPTOR_HANDLE *handlePtr = nullptr; + if (targets[0]->impl.depthStencilDescriptorHeap != nullptr) { + handle = targets[0]->impl.depthStencilDescriptorHeap->GetCPUDescriptorHandleForHeapStart(); + handlePtr = &handle; + } + list->impl._commandList->OMSetRenderTargets(count, &targetDescriptors[0], false, handlePtr); list->impl._commandList->RSSetViewports(1, (D3D12_VIEWPORT *)&targets[0]->impl.viewport); list->impl._commandList->RSSetScissorRects(1, (D3D12_RECT *)&targets[0]->impl.scissor); } @@ -345,7 +349,7 @@ void kinc_g5_command_list_upload_index_buffer(kinc_g5_command_list_t *list, kinc void kinc_g5_command_list_upload_texture(kinc_g5_command_list_t *list, kinc_g5_texture_t *texture) { D3D12_RESOURCE_DESC Desc = texture->impl.image->GetDesc(); - ID3D12Device* device; + ID3D12Device *device; texture->impl.image->GetDevice(IID_GRAPHICS_PPV_ARGS(&device)); D3D12_PLACED_SUBRESOURCE_FOOTPRINT footprint; device->GetCopyableFootprints(&Desc, 0, 1, 0, &footprint, nullptr, nullptr, nullptr); @@ -354,8 +358,8 @@ void kinc_g5_command_list_upload_texture(kinc_g5_command_list_t *list, kinc_g5_t CD3DX12_TEXTURE_COPY_LOCATION source(texture->impl.uploadImage, footprint); CD3DX12_TEXTURE_COPY_LOCATION destination(texture->impl.image, 0); list->impl._commandList->CopyTextureRegion(&destination, 0, 0, 0, &source, nullptr); - list->impl._commandList->ResourceBarrier( - 1, &CD3DX12_RESOURCE_BARRIER::Transition(texture->impl.image, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE)); + auto transition = CD3DX12_RESOURCE_BARRIER::Transition(texture->impl.image, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); + list->impl._commandList->ResourceBarrier(1, &transition); } #if defined(KORE_WINDOWS) || defined(KORE_WINDOWSAPP) @@ -372,17 +376,15 @@ void kinc_g5_command_list_get_render_target_pixels(kinc_g5_command_list_t *list, // Create readback buffer if (render_target->impl.renderTargetReadback == nullptr) { - device->CreateCommittedResource( - &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_READBACK), - D3D12_HEAP_FLAG_NONE, - &CD3DX12_RESOURCE_DESC::Buffer(render_target->texWidth * render_target->texHeight * formatByteSize), - D3D12_RESOURCE_STATE_COPY_DEST, - nullptr, - IID_GRAPHICS_PPV_ARGS(&render_target->impl.renderTargetReadback)); + auto heapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_READBACK); + auto bufferDesc = CD3DX12_RESOURCE_DESC::Buffer(render_target->texWidth * render_target->texHeight * formatByteSize); + device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &bufferDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, + IID_GRAPHICS_PPV_ARGS(&render_target->impl.renderTargetReadback)); } // Copy render target to readback buffer - D3D12_RESOURCE_STATES sourceState = render_target->impl.resourceState == RenderTargetResourceStateRenderTarget ? D3D12_RESOURCE_STATE_RENDER_TARGET : D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; + D3D12_RESOURCE_STATES sourceState = render_target->impl.resourceState == RenderTargetResourceStateRenderTarget ? D3D12_RESOURCE_STATE_RENDER_TARGET + : D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; { D3D12_RESOURCE_BARRIER barrier; @@ -429,7 +431,7 @@ void kinc_g5_command_list_get_render_target_pixels(kinc_g5_command_list_t *list, graphicsFlushAndWait(list, list->impl._commandAllocator, currentRenderTarget); // Read buffer - void* p; + void *p; render_target->impl.renderTargetReadback->Map(0, nullptr, &p); memcpy(data, p, render_target->texWidth * render_target->texHeight * formatByteSize); render_target->impl.renderTargetReadback->Unmap(0, nullptr); diff --git a/Backends/Graphics5/Direct3D12/Sources/Kore/ConstantBuffer5Impl.cpp b/Backends/Graphics5/Direct3D12/Sources/Kore/ConstantBuffer5Impl.cpp index dcbb75b93..9d8a2b714 100644 --- a/Backends/Graphics5/Direct3D12/Sources/Kore/ConstantBuffer5Impl.cpp +++ b/Backends/Graphics5/Direct3D12/Sources/Kore/ConstantBuffer5Impl.cpp @@ -12,11 +12,12 @@ void kinc_g5_constant_buffer_init(kinc_g5_constant_buffer_t *buffer, int size) { buffer->impl.mySize = size; buffer->data = nullptr; - kinc_microsoft_affirm(device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), D3D12_HEAP_FLAG_NONE, - &CD3DX12_RESOURCE_DESC::Buffer(size), D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, + auto heapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD); + auto bufferDesc = CD3DX12_RESOURCE_DESC::Buffer(size); + kinc_microsoft_affirm(device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &bufferDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_GRAPHICS_PPV_ARGS(&buffer->impl.constant_buffer))); - void* p; + void *p; buffer->impl.constant_buffer->Map(0, nullptr, &p); ZeroMemory(p, size); buffer->impl.constant_buffer->Unmap(0, nullptr); diff --git a/Backends/Graphics5/Direct3D12/Sources/Kore/Direct3D12.cpp b/Backends/Graphics5/Direct3D12/Sources/Kore/Direct3D12.cpp index 9c98a4ef1..349439442 100644 --- a/Backends/Graphics5/Direct3D12/Sources/Kore/Direct3D12.cpp +++ b/Backends/Graphics5/Direct3D12/Sources/Kore/Direct3D12.cpp @@ -48,7 +48,11 @@ ID3D12RootSignature *globalRootSignature; // ID3D12GraphicsCommandList* commandList; ID3D12Resource *depthStencilTexture; ID3D12CommandQueue *commandQueue; +#ifdef KORE_DIRECT3D_HAS_NO_SWAPCHAIN +ID3D12Resource *swapChainRenderTargets[QUEUE_SLOT_COUNT]; +#else IDXGISwapChain *swapChain; +#endif extern "C" { int renderTargetWidth; @@ -67,12 +71,20 @@ using namespace Kore; struct RenderEnvironment { ID3D12Device *device; ID3D12CommandQueue *queue; +#ifdef KORE_DIRECT3D_HAS_NO_SWAPCHAIN + ID3D12Resource *renderTargets[QUEUE_SLOT_COUNT]; +#else IDXGISwapChain *swapChain; +#endif }; #ifndef KORE_WINDOWS +#ifdef KORE_DIRECT3D_HAS_NO_SWAPCHAIN +void createSwapChain(RenderEnvironment *env, int bufferCount); +#else void createSwapChain(RenderEnvironment *env, const DXGI_SWAP_CHAIN_DESC1 *desc); #endif +#endif void createSamplersAndHeaps(); extern bool bilinearFiltering; @@ -107,8 +119,12 @@ namespace { DXGI_SWAP_CHAIN_DESC swapChainDescCopy = *swapChainDesc; kinc_microsoft_affirm(dxgiFactory->CreateSwapChain(result.queue, &swapChainDescCopy, &result.swapChain)); +#else +#ifdef KORE_DIRECT3D_HAS_NO_SWAPCHAIN + createSwapChain(&result, QUEUE_SLOT_COUNT); #else createSwapChain(&result, swapChainDesc); +#endif #endif return result; } @@ -141,8 +157,9 @@ namespace { clearValue.DepthStencil.Depth = 1.0f; clearValue.DepthStencil.Stencil = 0; - device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &depthTexture, - D3D12_RESOURCE_STATE_DEPTH_WRITE, &clearValue, IID_GRAPHICS_PPV_ARGS(&depthStencilTexture)); + auto heapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT); + device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &depthTexture, D3D12_RESOURCE_STATE_DEPTH_WRITE, &clearValue, + IID_GRAPHICS_PPV_ARGS(&depthStencilTexture)); device->CreateDepthStencilView(depthStencilTexture, nullptr, depthStencilDescriptorHeap->GetCPUDescriptorHandleForHeapStart()); @@ -186,7 +203,13 @@ namespace { device = renderEnv.device; commandQueue = renderEnv.queue; +#ifdef KORE_DIRECT3D_HAS_NO_SWAPCHAIN + for (int i = 0; i < QUEUE_SLOT_COUNT; ++i) { + swapChainRenderTargets[i] = renderEnv.renderTargets[i]; + } +#else swapChain = renderEnv.swapChain; +#endif setupSwapChain(); } @@ -356,6 +379,10 @@ namespace { bool began = false; } +#ifdef KORE_DIRECT3D_HAS_NO_SWAPCHAIN +extern "C" void kinc_internal_wait_for_frame(); +#endif + void kinc_g5_begin(kinc_g5_render_target_t *renderTarget, int window) { if (began) return; began = true; @@ -365,7 +392,9 @@ void kinc_g5_begin(kinc_g5_render_target_t *renderTarget, int window) { if (newRenderTargetWidth != renderTargetWidth || newRenderTargetHeight != renderTargetHeight) { depthStencilDescriptorHeap->Release(); depthStencilTexture->Release(); +#ifndef KORE_DIRECT3D_HAS_NO_SWAPCHAIN kinc_microsoft_affirm(swapChain->ResizeBuffers(2, newRenderTargetWidth, newRenderTargetHeight, DXGI_FORMAT_R8G8B8A8_UNORM, 0)); +#endif setupSwapChain(); renderTargetWidth = newRenderTargetWidth; renderTargetHeight = newRenderTargetHeight; @@ -383,6 +412,10 @@ void kinc_g5_begin(kinc_g5_render_target_t *renderTarget, int window) { waitForFence(frameFences[currentBackBuffer], fenceValues[currentBackBuffer], frameFenceEvents[currentBackBuffer]); +#ifdef KORE_DIRECT3D_HAS_NO_SWAPCHAIN + kinc_internal_wait_for_frame(); +#endif + // static const float clearColor[] = {0.042f, 0.042f, 0.042f, 1}; // commandList->ClearRenderTargetView(renderTargetDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), clearColor, 0, nullptr); @@ -413,10 +446,12 @@ extern "C" void kinc_internal_resize(int window, int width, int height) { extern "C" void kinc_internal_change_framebuffer(int window, kinc_framebuffer_options_t *frame) {} +#ifndef KORE_DIRECT3D_HAS_NO_SWAPCHAIN bool kinc_g5_swap_buffers() { kinc_microsoft_affirm(swapChain->Present(vsync, 0)); return true; } +#endif void kinc_g5_flush() {} diff --git a/Backends/Graphics5/Direct3D12/Sources/Kore/IndexBuffer5Impl.cpp b/Backends/Graphics5/Direct3D12/Sources/Kore/IndexBuffer5Impl.cpp index dfc0f87c5..985439df0 100644 --- a/Backends/Graphics5/Direct3D12/Sources/Kore/IndexBuffer5Impl.cpp +++ b/Backends/Graphics5/Direct3D12/Sources/Kore/IndexBuffer5Impl.cpp @@ -18,13 +18,18 @@ void kinc_g5_index_buffer_init(kinc_g5_index_buffer_t *buffer, int count, bool g static_assert(sizeof(D3D12IindexBufferView) == sizeof(D3D12_INDEX_BUFFER_VIEW), "Something is wrong with D3D12IindexBufferView"); int uploadBufferSize = sizeof(int) * count; - kinc_microsoft_affirm(device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize), - D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_GRAPHICS_PPV_ARGS(&buffer->impl.uploadBuffer))); + { + auto heapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD); + auto bufferDesc = CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize); + kinc_microsoft_affirm(device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &bufferDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, + IID_GRAPHICS_PPV_ARGS(&buffer->impl.uploadBuffer))); + } if (gpuMemory) { - kinc_microsoft_affirm(device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, - &CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize), D3D12_RESOURCE_STATE_COPY_DEST, nullptr, - IID_GRAPHICS_PPV_ARGS(&buffer->impl.indexBuffer))); + auto heapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT); + auto bufferDesc = CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize); + kinc_microsoft_affirm(device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &bufferDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, + IID_GRAPHICS_PPV_ARGS(&buffer->impl.indexBuffer))); buffer->impl.indexBufferView.BufferLocation = buffer->impl.indexBuffer->GetGPUVirtualAddress(); } @@ -41,9 +46,9 @@ void kinc_g5_index_buffer_destroy(kinc_g5_index_buffer_t *buffer) { } int *kinc_g5_index_buffer_lock(kinc_g5_index_buffer_t *buffer) { - void* p; + void *p; buffer->impl.uploadBuffer->Map(0, nullptr, &p); - return (int*)p; + return (int *)p; } void kinc_g5_index_buffer_unlock(kinc_g5_index_buffer_t *buffer) { diff --git a/Backends/Graphics5/Direct3D12/Sources/Kore/PipelineState5Impl.cpp b/Backends/Graphics5/Direct3D12/Sources/Kore/PipelineState5Impl.cpp index 6d0afef74..9995a91ba 100644 --- a/Backends/Graphics5/Direct3D12/Sources/Kore/PipelineState5Impl.cpp +++ b/Backends/Graphics5/Direct3D12/Sources/Kore/PipelineState5Impl.cpp @@ -35,7 +35,7 @@ void kinc_g5_internal_setConstants(ID3D12GraphicsCommandList *commandList, kinc_ */ commandList->SetPipelineState(pipeline->impl.pso); -#ifdef KORE_DXC +#ifdef KORE_DXC_DISABLED commandList->SetGraphicsRootSignature(pipeline->impl.rootSignature); #else commandList->SetGraphicsRootSignature(globalRootSignature); @@ -244,9 +244,9 @@ namespace { case KINC_G5_RENDER_TARGET_FORMAT_32BIT: default: #ifdef KORE_WINDOWS - return DXGI_FORMAT_R8G8B8A8_UNORM; + return DXGI_FORMAT_R8G8B8A8_UNORM; #else - return DXGI_FORMAT_B8G8R8A8_UNORM; + return DXGI_FORMAT_B8G8R8A8_UNORM; #endif } } @@ -304,7 +304,7 @@ void kinc_g5_pipeline_compile(kinc_g5_pipeline_t *pipe) { } HRESULT hr; -#ifdef KORE_DXC +#ifdef KORE_DXC_DISABLED hr = device->CreateRootSignature(0, pipe->vertexShader->impl.data, pipe->vertexShader->impl.length, IID_GRAPHICS_PPV_ARGS(&pipe->impl.rootSignature)); if (hr != S_OK) { kinc_log(KINC_LOG_LEVEL_WARNING, "Could not create root signature."); @@ -320,7 +320,7 @@ void kinc_g5_pipeline_compile(kinc_g5_pipeline_t *pipe) { psoDesc.VS.pShaderBytecode = pipe->vertexShader->impl.data; psoDesc.PS.BytecodeLength = pipe->fragmentShader->impl.length; psoDesc.PS.pShaderBytecode = pipe->fragmentShader->impl.data; -#ifdef KORE_DXC +#ifdef KORE_DXC_DISABLED psoDesc.pRootSignature = pipe->impl.rootSignature; #else psoDesc.pRootSignature = globalRootSignature; diff --git a/Backends/Graphics5/Direct3D12/Sources/Kore/PipelineState5Impl.h b/Backends/Graphics5/Direct3D12/Sources/Kore/PipelineState5Impl.h index 4c6e031db..09cf09ca5 100644 --- a/Backends/Graphics5/Direct3D12/Sources/Kore/PipelineState5Impl.h +++ b/Backends/Graphics5/Direct3D12/Sources/Kore/PipelineState5Impl.h @@ -12,7 +12,7 @@ struct ID3D12RootSignature; typedef struct { struct ID3D12PipelineState *pso; -#ifdef KORE_DXC +#ifdef KORE_DXC_DISABLED struct ID3D12RootSignature *rootSignature; int vertexConstantsSize; int fragmentConstantsSize; diff --git a/Backends/Graphics5/Direct3D12/Sources/Kore/RenderTarget5Impl.cpp b/Backends/Graphics5/Direct3D12/Sources/Kore/RenderTarget5Impl.cpp index 6b80ecbec..845736c62 100644 --- a/Backends/Graphics5/Direct3D12/Sources/Kore/RenderTarget5Impl.cpp +++ b/Backends/Graphics5/Direct3D12/Sources/Kore/RenderTarget5Impl.cpp @@ -15,7 +15,11 @@ static const int textureCount = 16; extern kinc_g5_texture_t *currentTextures[textureCount]; extern kinc_g5_render_target_t *currentRenderTargets[textureCount]; +#ifdef KORE_DIRECT3D_HAS_NO_SWAPCHAIN +extern ID3D12Resource *swapChainRenderTargets[QUEUE_SLOT_COUNT]; +#else extern IDXGISwapChain *swapChain; +#endif namespace { ID3D12Fence *renderFence; @@ -83,23 +87,29 @@ void kinc_g5_render_target_init(kinc_g5_render_target_t *render_target, int widt clearValue.Color[2] = 0.0f; clearValue.Color[3] = 1.0f; - HRESULT result = device->CreateCommittedResource( - &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, - &CD3DX12_RESOURCE_DESC::Tex2D(dxgiFormat, render_target->texWidth, render_target->texHeight, 1, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET), - D3D12_RESOURCE_STATE_COMMON, &clearValue, IID_GRAPHICS_PPV_ARGS(&render_target->impl.renderTarget)); + HRESULT result; + { + auto heapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT); + auto resourceDesc = + CD3DX12_RESOURCE_DESC::Tex2D(dxgiFormat, render_target->texWidth, render_target->texHeight, 1, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET); + result = device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &resourceDesc, D3D12_RESOURCE_STATE_COMMON, &clearValue, + IID_GRAPHICS_PPV_ARGS(&render_target->impl.renderTarget)); + } + if (result != S_OK) { for (int i = 0; i < 10; ++i) { kinc_memory_emergency(); - result = device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, - &CD3DX12_RESOURCE_DESC::Tex2D(dxgiFormat, render_target->texWidth, render_target->texHeight, 1, 1, 1, 0, - D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET), - D3D12_RESOURCE_STATE_COMMON, &clearValue, IID_GRAPHICS_PPV_ARGS(&render_target->impl.renderTarget)); + auto heapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT); + auto resourceDesc = CD3DX12_RESOURCE_DESC::Tex2D(dxgiFormat, render_target->texWidth, render_target->texHeight, 1, 1, 1, 0, + D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET); + result = device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &resourceDesc, D3D12_RESOURCE_STATE_COMMON, &clearValue, + IID_GRAPHICS_PPV_ARGS(&render_target->impl.renderTarget)); if (result == S_OK) { break; } } } - + D3D12_RENDER_TARGET_VIEW_DESC view; const D3D12_RESOURCE_DESC resourceDesc = render_target->impl.renderTarget->GetDesc(); view.Format = dxgiFormat; @@ -151,13 +161,18 @@ void kinc_g5_render_target_init(kinc_g5_render_target_t *render_target, int widt clearValue.DepthStencil.Depth = 1.0f; clearValue.DepthStencil.Stencil = 0; - HRESULT result = device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &depthTexture, - D3D12_RESOURCE_STATE_DEPTH_WRITE, &clearValue, IID_GRAPHICS_PPV_ARGS(&render_target->impl.depthStencilTexture)); + HRESULT result; + { + auto heapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT); + result = device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &depthTexture, D3D12_RESOURCE_STATE_DEPTH_WRITE, &clearValue, + IID_GRAPHICS_PPV_ARGS(&render_target->impl.depthStencilTexture)); + } + if (result != S_OK) { for (int i = 0; i < 10; ++i) { kinc_memory_emergency(); - result = device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &depthTexture, - D3D12_RESOURCE_STATE_DEPTH_WRITE, &clearValue, + auto heapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT); + result = device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &depthTexture, D3D12_RESOURCE_STATE_DEPTH_WRITE, &clearValue, IID_GRAPHICS_PPV_ARGS(&render_target->impl.depthStencilTexture)); if (result == S_OK) { break; @@ -196,7 +211,11 @@ void kinc_g5_render_target_init(kinc_g5_render_target_t *render_target, int widt render_target->impl.viewport = {0.0f, 0.0f, static_cast(width), static_cast(height), 0.0f, 1.0f}; if (contextId < 0) { // encoded backbuffer index +#ifdef KORE_DIRECT3D_HAS_NO_SWAPCHAIN + render_target->impl.renderTarget = swapChainRenderTargets[-contextId - 1]; +#else swapChain->GetBuffer(-contextId - 1, IID_GRAPHICS_PPV_ARGS(&render_target->impl.renderTarget)); +#endif createRenderTargetView(render_target->impl.renderTarget, render_target->impl.renderTargetDescriptorHeap, dxgiFormat); } } diff --git a/Backends/Graphics5/Direct3D12/Sources/Kore/Texture5Impl.cpp b/Backends/Graphics5/Direct3D12/Sources/Kore/Texture5Impl.cpp index b1875ee7f..4269bf6d4 100644 --- a/Backends/Graphics5/Direct3D12/Sources/Kore/Texture5Impl.cpp +++ b/Backends/Graphics5/Direct3D12/Sources/Kore/Texture5Impl.cpp @@ -19,12 +19,12 @@ kinc_g5_texture *currentTextures[textureCount] = {nullptr, nullptr, nullptr, nul bool bilinearFiltering = false; namespace { - ID3D12DescriptorHeap* samplerDescriptorHeapPoint; - ID3D12DescriptorHeap* samplerDescriptorHeapBilinear; + ID3D12DescriptorHeap *samplerDescriptorHeapPoint; + ID3D12DescriptorHeap *samplerDescriptorHeapBilinear; static const int heapSize = 1024; static int heapIndex = 0; - ID3D12DescriptorHeap* srvHeap; - ID3D12DescriptorHeap* samplerHeap; + ID3D12DescriptorHeap *srvHeap; + ID3D12DescriptorHeap *samplerHeap; } #if defined(KORE_WINDOWS) || defined(KORE_WINDOWSAPP) @@ -80,7 +80,7 @@ static int formatByteSize(kinc_image_format_t format) { } } -void kinc_g5_internal_set_textures(ID3D12GraphicsCommandList* commandList) { +void kinc_g5_internal_set_textures(ID3D12GraphicsCommandList *commandList) { if (currentRenderTargets[0] != nullptr || currentTextures[0] != nullptr) { int srvStep = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); int samplerStep = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); @@ -89,7 +89,7 @@ void kinc_g5_internal_set_textures(ID3D12GraphicsCommandList* commandList) { heapIndex = 0; } - ID3D12DescriptorHeap* samplerDescriptorHeap = bilinearFiltering ? samplerDescriptorHeapBilinear : samplerDescriptorHeapPoint; + ID3D12DescriptorHeap *samplerDescriptorHeap = bilinearFiltering ? samplerDescriptorHeapBilinear : samplerDescriptorHeapPoint; D3D12_GPU_DESCRIPTOR_HANDLE srvGpu = srvHeap->GetGPUDescriptorHandleForHeapStart(); D3D12_GPU_DESCRIPTOR_HANDLE samplerGpu = samplerHeap->GetGPUDescriptorHandleForHeapStart(); srvGpu.ptr += heapIndex * srvStep; @@ -106,11 +106,12 @@ void kinc_g5_internal_set_textures(ID3D12GraphicsCommandList* commandList) { if (currentRenderTargets[i] != nullptr) { bool is_depth = currentRenderTargets[i]->impl.stage_depth == i; - D3D12_CPU_DESCRIPTOR_HANDLE sourceCpu = is_depth ? - currentRenderTargets[i]->impl.srvDepthDescriptorHeap->GetCPUDescriptorHandleForHeapStart() : - currentRenderTargets[i]->impl.srvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(); + D3D12_CPU_DESCRIPTOR_HANDLE sourceCpu = is_depth + ? currentRenderTargets[i]->impl.srvDepthDescriptorHeap->GetCPUDescriptorHandleForHeapStart() + : currentRenderTargets[i]->impl.srvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(); device->CopyDescriptorsSimple(1, srvCpu, sourceCpu, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - device->CopyDescriptorsSimple(1, samplerCpu, samplerDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); + device->CopyDescriptorsSimple(1, samplerCpu, samplerDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), + D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); if (is_depth) { currentRenderTargets[i]->impl.stage_depth = -1; @@ -120,12 +121,13 @@ void kinc_g5_internal_set_textures(ID3D12GraphicsCommandList* commandList) { else { D3D12_CPU_DESCRIPTOR_HANDLE sourceCpu = currentTextures[i]->impl.srvDescriptorHeap->GetCPUDescriptorHandleForHeapStart(); device->CopyDescriptorsSimple(1, srvCpu, sourceCpu, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - device->CopyDescriptorsSimple(1, samplerCpu, samplerDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); + device->CopyDescriptorsSimple(1, samplerCpu, samplerDescriptorHeap->GetCPUDescriptorHandleForHeapStart(), + D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); } } } - ID3D12DescriptorHeap* heaps[2] = {srvHeap, samplerHeap}; + ID3D12DescriptorHeap *heaps[2] = {srvHeap, samplerHeap}; commandList->SetDescriptorHeaps(2, heaps); commandList->SetGraphicsRootDescriptorTable(0, srvGpu); commandList->SetGraphicsRootDescriptorTable(1, samplerGpu); @@ -142,9 +144,9 @@ static void createSampler(bool bilinear, D3D12_FILTER filter) { D3D12_SAMPLER_DESC samplerDesc; ZeroMemory(&samplerDesc, sizeof(D3D12_SAMPLER_DESC)); samplerDesc.Filter = filter; - samplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP; - samplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP; - samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP; + samplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + samplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; samplerDesc.MinLOD = 0; samplerDesc.MaxLOD = D3D12_FLOAT32_MAX; samplerDesc.MipLODBias = 0.0f; @@ -182,15 +184,21 @@ void kinc_g5_texture_init_from_image(kinc_g5_texture_t *texture, kinc_image_t *i DXGI_FORMAT d3dformat = convertFormat(image->format); int formatSize = formatByteSize(image->format); - HRESULT result = device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, - &CD3DX12_RESOURCE_DESC::Tex2D(d3dformat, texture->texWidth, texture->texHeight, 1, 1), - D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_GRAPHICS_PPV_ARGS(&texture->impl.image)); + HRESULT result; + { + auto heapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT); + auto resourceDesc = CD3DX12_RESOURCE_DESC::Tex2D(d3dformat, texture->texWidth, texture->texHeight, 1, 1); + result = device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &resourceDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, + IID_GRAPHICS_PPV_ARGS(&texture->impl.image)); + } + if (result != S_OK) { for (int i = 0; i < 10; ++i) { kinc_memory_emergency(); - result = device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, - &CD3DX12_RESOURCE_DESC::Tex2D(d3dformat, texture->texWidth, texture->texHeight, 1, 1), - D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_GRAPHICS_PPV_ARGS(&texture->impl.image)); + auto heapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT); + auto resourceDesc = CD3DX12_RESOURCE_DESC::Tex2D(d3dformat, texture->texWidth, texture->texHeight, 1, 1); + result = device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &resourceDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, + IID_GRAPHICS_PPV_ARGS(&texture->impl.image)); if (result == S_OK) { break; } @@ -198,13 +206,20 @@ void kinc_g5_texture_init_from_image(kinc_g5_texture_t *texture, kinc_image_t *i } const UINT64 uploadBufferSize = GetRequiredIntermediateSize(texture->impl.image, 0, 1); - result = device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize), - D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_GRAPHICS_PPV_ARGS(&texture->impl.uploadImage)); + + { + auto heapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD); + auto bufferDesc = CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize); + result = device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &bufferDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, + IID_GRAPHICS_PPV_ARGS(&texture->impl.uploadImage)); + } + if (result != S_OK) { for (int i = 0; i < 10; ++i) { kinc_memory_emergency(); - result = device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), D3D12_HEAP_FLAG_NONE, - &CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize), D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, + auto heapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD); + auto bufferDesc = CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize); + result = device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &bufferDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_GRAPHICS_PPV_ARGS(&texture->impl.uploadImage)); if (result == S_OK) { break; @@ -221,7 +236,7 @@ void kinc_g5_texture_init_from_image(kinc_g5_texture_t *texture, kinc_image_t *i texture->impl.uploadImage->Map(0, nullptr, reinterpret_cast(&pixel)); int pitch = kinc_g5_texture_stride(texture); for (int y = 0; y < texture->texHeight; ++y) { - memcpy(&pixel[y * pitch], &((uint8_t*)image->data)[y * texture->texWidth * formatSize], texture->texWidth * formatSize); + memcpy(&pixel[y * pitch], &((uint8_t *)image->data)[y * texture->texWidth * formatSize], texture->texWidth * formatSize); } texture->impl.uploadImage->Unmap(0, nullptr); @@ -246,7 +261,7 @@ void kinc_g5_texture_init_from_image(kinc_g5_texture_t *texture, kinc_image_t *i } void create_texture(kinc_g5_texture *texture, int width, int height, kinc_image_format_t format, D3D12_RESOURCE_FLAGS flags) { - //kinc_image_init(&texture->image, width, height, format, readable); + // kinc_image_init(&texture->image, width, height, format, readable); memset(&texture->impl, 0, sizeof(texture->impl)); texture->impl.stage = 0; texture->impl.mipmap = true; @@ -255,14 +270,21 @@ void create_texture(kinc_g5_texture *texture, int width, int height, kinc_image_ DXGI_FORMAT d3dformat = convertFormat(format); - HRESULT result = device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, - &CD3DX12_RESOURCE_DESC::Tex2D(d3dformat, texture->texWidth, texture->texHeight, 1, 1, 1, 0, flags), D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_GRAPHICS_PPV_ARGS(&texture->impl.image)); + HRESULT result; + { + auto heapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT); + auto resourceDesc = CD3DX12_RESOURCE_DESC::Tex2D(d3dformat, texture->texWidth, texture->texHeight, 1, 1, 1, 0, flags); + result = device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &resourceDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, + IID_GRAPHICS_PPV_ARGS(&texture->impl.image)); + } + if (result != S_OK) { for (int i = 0; i < 10; ++i) { kinc_memory_emergency(); - result = device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, - &CD3DX12_RESOURCE_DESC::Tex2D(d3dformat, texture->texWidth, texture->texHeight, 1, 1, 1, 0, flags), - D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_GRAPHICS_PPV_ARGS(&texture->impl.image)); + auto heapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT); + auto resourceDesc = CD3DX12_RESOURCE_DESC::Tex2D(d3dformat, texture->texWidth, texture->texHeight, 1, 1, 1, 0, flags); + result = device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &resourceDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, + IID_GRAPHICS_PPV_ARGS(&texture->impl.image)); if (result == S_OK) { break; } @@ -270,13 +292,19 @@ void create_texture(kinc_g5_texture *texture, int width, int height, kinc_image_ } const UINT64 uploadBufferSize = GetRequiredIntermediateSize(texture->impl.image, 0, 1); - result = device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize), - D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_GRAPHICS_PPV_ARGS(&texture->impl.uploadImage)); + { + auto heapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD); + auto bufferDesc = CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize); + result = device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &bufferDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, + IID_GRAPHICS_PPV_ARGS(&texture->impl.uploadImage)); + } + if (result != S_OK) { for (int i = 0; i < 10; ++i) { kinc_memory_emergency(); - result = device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), D3D12_HEAP_FLAG_NONE, - &CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize), D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, + auto heapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD); + auto bufferDesc = CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize); + result = device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &bufferDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_GRAPHICS_PPV_ARGS(&texture->impl.uploadImage)); if (result == S_OK) { break; @@ -314,7 +342,7 @@ void kinc_g5_texture_init(kinc_g5_texture *texture, int width, int height, kinc_ } void kinc_g5_texture_init3d(kinc_g5_texture *texture, int width, int height, int depth, kinc_image_format_t format, bool readable) { - //kinc_image_init3d(&texture->image, width, height, depth, format, readable); + // kinc_image_init3d(&texture->image, width, height, depth, format, readable); } void kinc_g5_texture_init_non_sampled_access(kinc_g5_texture *texture, int width, int height, kinc_image_format_t format) { @@ -365,9 +393,9 @@ int kinc_g5_texture_stride(kinc_g5_texture *texture) { /*int baseStride = texture->format == KINC_IMAGE_FORMAT_RGBA32 ? (texture->texWidth * 4) : texture->texWidth; if (texture->format == KINC_IMAGE_FORMAT_GREY8) return texture->texWidth; // please investigate further for (int i = 0;; ++i) { - if (d3d12_textureAlignment() * i >= baseStride) { - return d3d12_textureAlignment() * i; - } + if (d3d12_textureAlignment() * i >= baseStride) { + return d3d12_textureAlignment() * i; + } }*/ return texture->impl.stride; } diff --git a/Backends/Graphics5/Direct3D12/Sources/Kore/VertexBuffer5Impl.cpp b/Backends/Graphics5/Direct3D12/Sources/Kore/VertexBuffer5Impl.cpp index ee5c881d7..0d608d9a9 100644 --- a/Backends/Graphics5/Direct3D12/Sources/Kore/VertexBuffer5Impl.cpp +++ b/Backends/Graphics5/Direct3D12/Sources/Kore/VertexBuffer5Impl.cpp @@ -46,8 +46,10 @@ void kinc_g5_vertex_buffer_init(kinc_g5_vertex_buffer_t *buffer, int count, kinc int uploadBufferSize = buffer->impl.myStride * buffer->impl.myCount; - device->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize), - D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_GRAPHICS_PPV_ARGS(&buffer->impl.uploadBuffer)); + auto heapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD); + auto bufferDesc = CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize); + device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &bufferDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, + IID_GRAPHICS_PPV_ARGS(&buffer->impl.uploadBuffer)); // device_->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES (D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, // &CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize), @@ -70,14 +72,14 @@ float *kinc_g5_vertex_buffer_lock_all(kinc_g5_vertex_buffer_t *buffer) { float *kinc_g5_vertex_buffer_lock(kinc_g5_vertex_buffer_t *buffer, int start, int count) { buffer->impl.lastStart = start; buffer->impl.lastCount = count; - void* p; + void *p; D3D12_RANGE range; range.Begin = start * buffer->impl.myStride; range.End = range.Begin + count * buffer->impl.myStride; buffer->impl.uploadBuffer->Map(0, &range, &p); - byte* bytes = (byte*)p; + byte *bytes = (byte *)p; bytes += start * buffer->impl.myStride; - return (float*)bytes; + return (float *)bytes; } void kinc_g5_vertex_buffer_unlock_all(kinc_g5_vertex_buffer_t *buffer) { diff --git a/Backends/Graphics5/Vulkan/Sources/Kore/CommandList5Impl.cpp b/Backends/Graphics5/Vulkan/Sources/Kore/CommandList5Impl.cpp index 967e0c45a..b090310b0 100644 --- a/Backends/Graphics5/Vulkan/Sources/Kore/CommandList5Impl.cpp +++ b/Backends/Graphics5/Vulkan/Sources/Kore/CommandList5Impl.cpp @@ -15,29 +15,73 @@ #include extern VkDevice device; +extern VkRenderPass framebuffer_render_pass; +extern VkRenderPass rendertarget_render_pass; extern VkCommandPool cmd_pool; extern PFN_vkQueuePresentKHR fpQueuePresentKHR; -extern PFN_vkAcquireNextImageKHR fpAcquireNextImageKHR; extern VkSwapchainKHR swapchain; extern VkQueue queue; extern VkFramebuffer *framebuffers; -extern VkRenderPass render_pass; -extern VkDescriptorSet desc_set; -extern kinc_g5_texture_t *vulkanTextures[8]; -extern kinc_g5_render_target_t *vulkanRenderTargets[8]; extern uint32_t current_buffer; +extern int depthBits; +extern VkSemaphore presentCompleteSemaphore; +extern kinc_g5_texture_t *vulkanTextures[16]; +extern kinc_g5_render_target_t *vulkanRenderTargets[16]; +VkDescriptorSet getDescriptorSet(); +bool memory_type_from_properties(uint32_t typeBits, VkFlags requirements_mask, uint32_t *typeIndex); +void setImageLayout(VkCommandBuffer _buffer, VkImage image, VkImageAspectFlags aspectMask, VkImageLayout oldImageLayout, VkImageLayout newImageLayout); +VkCommandBuffer setup_cmd; +VkRenderPassBeginInfo currentRenderPassBeginInfo; +VkPipeline currentVulkanPipeline; +kinc_g5_render_target_t *currentRenderTargets[8] = {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}; + +static void set_barriers(kinc_g5_command_list_t *list); namespace { - VkCommandBuffer setup_cmd; bool began = false; bool onBackBuffer = false; uint32_t lastVertexConstantBufferOffset = 0; uint32_t lastFragmentConstantBufferOffset = 0; kinc_g5_pipeline_t *currentPipeline = NULL; + int mrtIndex = 0; + VkFramebuffer mrtFramebuffer[16]; + VkRenderPass mrtRenderPass[16]; + + void endPass(kinc_g5_command_list_t *list) { + vkCmdEndRenderPass(list->impl._buffer); + if (currentRenderTargets[0] != nullptr && currentRenderTargets[0]->contextId >= 0) { + int i = 0; + while (currentRenderTargets[i] != nullptr) { + kinc_g5_command_list_render_target_to_texture_barrier(list, currentRenderTargets[i]); + i++; + } + } + + for (int i = 0; i < 16; ++i) { + vulkanTextures[i] = nullptr; + vulkanRenderTargets[i] = nullptr; + } + } + + int formatSize(VkFormat format) { + switch (format) { + case VK_FORMAT_R32G32B32A32_SFLOAT: + return 16; + case VK_FORMAT_R16G16B16A16_SFLOAT: + return 8; + case VK_FORMAT_R16_SFLOAT: + return 2; + case VK_FORMAT_R8_UNORM: + return 1; + default: + return 4; + } + } } -void Kore::Vulkan::demo_set_image_layout(VkImage image, VkImageAspectFlags aspectMask, VkImageLayout old_image_layout, VkImageLayout new_image_layout) { +void set_image_layout(VkImage image, VkImageAspectFlags aspectMask, VkImageLayout old_image_layout, VkImageLayout new_image_layout) { VkResult err; + if (setup_cmd == VK_NULL_HANDLE) { VkCommandBufferAllocateInfo cmd = {}; cmd.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; @@ -49,21 +93,11 @@ void Kore::Vulkan::demo_set_image_layout(VkImage image, VkImageAspectFlags aspec err = vkAllocateCommandBuffers(device, &cmd, &setup_cmd); assert(!err); - VkCommandBufferInheritanceInfo cmd_buf_hinfo = {}; - cmd_buf_hinfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO; - cmd_buf_hinfo.pNext = nullptr; - cmd_buf_hinfo.renderPass = VK_NULL_HANDLE; - cmd_buf_hinfo.subpass = 0; - cmd_buf_hinfo.framebuffer = VK_NULL_HANDLE; - cmd_buf_hinfo.occlusionQueryEnable = VK_FALSE; - cmd_buf_hinfo.queryFlags = 0; - cmd_buf_hinfo.pipelineStatistics = 0; - VkCommandBufferBeginInfo cmd_buf_info = {}; cmd_buf_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; cmd_buf_info.pNext = nullptr; cmd_buf_info.flags = 0; - cmd_buf_info.pInheritanceInfo = &cmd_buf_hinfo; + cmd_buf_info.pInheritanceInfo = NULL; err = vkBeginCommandBuffer(setup_cmd, &cmd_buf_info); assert(!err); @@ -109,8 +143,8 @@ void Kore::Vulkan::demo_set_image_layout(VkImage image, VkImageAspectFlags aspec image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; } - VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; + VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; if (new_image_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { dstStageMask = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; } @@ -121,7 +155,30 @@ void Kore::Vulkan::demo_set_image_layout(VkImage image, VkImageAspectFlags aspec vkCmdPipelineBarrier(setup_cmd, srcStageMask, dstStageMask, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier); } -void Kore::Vulkan::demo_flush_init_cmd() { +void setup_init_cmd() { + if (setup_cmd == VK_NULL_HANDLE) { + VkCommandBufferAllocateInfo cmd = {}; + cmd.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + cmd.pNext = NULL; + cmd.commandPool = cmd_pool; + cmd.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + cmd.commandBufferCount = 1; + + VkResult err = vkAllocateCommandBuffers(device, &cmd, &setup_cmd); + assert(!err); + + VkCommandBufferBeginInfo cmd_buf_info = {}; + cmd_buf_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + cmd_buf_info.pNext = NULL; + cmd_buf_info.flags = 0; + cmd_buf_info.pInheritanceInfo = NULL; + + err = vkBeginCommandBuffer(setup_cmd, &cmd_buf_info); + assert(!err); + } +} + +void flush_init_cmd() { VkResult err; if (setup_cmd == VK_NULL_HANDLE) return; @@ -152,12 +209,40 @@ void Kore::Vulkan::demo_flush_init_cmd() { setup_cmd = VK_NULL_HANDLE; } -namespace { - float depthStencil; - float depthIncrement; -} +void set_viewport_and_scissor(kinc_g5_command_list_t *list) { + VkViewport viewport; + memset(&viewport, 0, sizeof(viewport)); + VkRect2D scissor; + memset(&scissor, 0, sizeof(scissor)); -extern VkSemaphore presentCompleteSemaphore; + if (currentRenderTargets[0] == nullptr || currentRenderTargets[0]->contextId < 0) { + viewport.x = 0; + viewport.y = (float)kinc_height(); + viewport.width = (float)kinc_width(); + viewport.height = -(float)kinc_height(); + viewport.minDepth = (float)0.0f; + viewport.maxDepth = (float)1.0f; + scissor.extent.width = kinc_width(); + scissor.extent.height = kinc_height(); + scissor.offset.x = 0; + scissor.offset.y = 0; + } + else { + viewport.x = 0; + viewport.y = (float)currentRenderTargets[0]->height; + viewport.width = (float)currentRenderTargets[0]->width; + viewport.height = -(float)currentRenderTargets[0]->height; + viewport.minDepth = (float)0.0f; + viewport.maxDepth = (float)1.0f; + scissor.extent.width = currentRenderTargets[0]->width; + scissor.extent.height = currentRenderTargets[0]->height; + scissor.offset.x = 0; + scissor.offset.y = 0; + } + + vkCmdSetViewport(list->impl._buffer, 0, 1, &viewport); + vkCmdSetScissor(list->impl._buffer, 0, 1, &scissor); +} void kinc_g5_command_list_init(kinc_g5_command_list_t *list) { VkCommandBufferAllocateInfo cmd = {}; @@ -171,38 +256,16 @@ void kinc_g5_command_list_init(kinc_g5_command_list_t *list) { assert(!err); list->impl._indexCount = 0; - - depthStencil = 1.0; - depthIncrement = -0.01f; - - // begin(); } void kinc_g5_command_list_destroy(kinc_g5_command_list_t *list) {} void kinc_g5_command_list_begin(kinc_g5_command_list_t *list) { - // if (began) return; - - // Assume the command buffer has been run on current_buffer before so - // we need to set the image layout back to COLOR_ATTACHMENT_OPTIMAL - // demo_set_image_layout(Vulkan::buffers[current_buffer].image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, - // VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); demo_flush_init_cmd(); - - VkCommandBufferInheritanceInfo cmd_buf_hinfo = {}; - cmd_buf_hinfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO; - cmd_buf_hinfo.pNext = NULL; - cmd_buf_hinfo.renderPass = VK_NULL_HANDLE; - cmd_buf_hinfo.subpass = 0; - cmd_buf_hinfo.framebuffer = VK_NULL_HANDLE; - cmd_buf_hinfo.occlusionQueryEnable = VK_FALSE; - cmd_buf_hinfo.queryFlags = 0; - cmd_buf_hinfo.pipelineStatistics = 0; - VkCommandBufferBeginInfo cmd_buf_info = {}; cmd_buf_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; cmd_buf_info.pNext = NULL; cmd_buf_info.flags = 0; - cmd_buf_info.pInheritanceInfo = &cmd_buf_hinfo; + cmd_buf_info.pInheritanceInfo = NULL; VkClearValue clear_values[2]; memset(clear_values, 0, sizeof(VkClearValue) * 2); @@ -210,19 +273,21 @@ void kinc_g5_command_list_begin(kinc_g5_command_list_t *list) { clear_values[0].color.float32[1] = 0.0f; clear_values[0].color.float32[2] = 0.0f; clear_values[0].color.float32[3] = 1.0f; - clear_values[1].depthStencil.depth = depthStencil; - clear_values[1].depthStencil.stencil = 0; + if (depthBits > 0) { + clear_values[1].depthStencil.depth = 1.0; + clear_values[1].depthStencil.stencil = 0; + } VkRenderPassBeginInfo rp_begin = {}; rp_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; rp_begin.pNext = NULL; - rp_begin.renderPass = render_pass; + rp_begin.renderPass = framebuffer_render_pass; rp_begin.framebuffer = framebuffers[current_buffer]; rp_begin.renderArea.offset.x = 0; rp_begin.renderArea.offset.y = 0; rp_begin.renderArea.extent.width = kinc_width(); rp_begin.renderArea.extent.height = kinc_height(); - rp_begin.clearValueCount = 2; + rp_begin.clearValueCount = depthBits > 0 ? 2 : 1; rp_begin.pClearValues = clear_values; VkResult err = vkBeginCommandBuffer(list->impl._buffer, &cmd_buf_info); @@ -245,25 +310,18 @@ void kinc_g5_command_list_begin(kinc_g5_command_list_t *list) { pmemory_barrier); vkCmdBeginRenderPass(list->impl._buffer, &rp_begin, VK_SUBPASS_CONTENTS_INLINE); + currentRenderPassBeginInfo = rp_begin; - VkViewport viewport; - memset(&viewport, 0, sizeof(viewport)); - viewport.width = (float)kinc_width(); - viewport.height = (float)kinc_height(); - viewport.minDepth = (float)0.0f; - viewport.maxDepth = (float)1.0f; - vkCmdSetViewport(list->impl._buffer, 0, 1, &viewport); - - VkRect2D scissor; - memset(&scissor, 0, sizeof(scissor)); - scissor.extent.width = kinc_width(); - scissor.extent.height = kinc_height(); - scissor.offset.x = 0; - scissor.offset.y = 0; - vkCmdSetScissor(list->impl._buffer, 0, 1, &scissor); + set_viewport_and_scissor(list); began = true; onBackBuffer = true; + + for (int i = 0; i < mrtIndex; ++i) { + vkDestroyFramebuffer(device, mrtFramebuffer[i], nullptr); + vkDestroyRenderPass(device, mrtRenderPass[i], nullptr); + } + mrtIndex = 0; } void kinc_g5_command_list_end(kinc_g5_command_list_t *list) { @@ -310,33 +368,12 @@ void kinc_g5_command_list_end(kinc_g5_command_list_t *list) { present.pSwapchains = &swapchain; present.pImageIndices = ¤t_buffer; - // TBD/TODO: SHOULD THE "present" PARAMETER BE "const" IN THE HEADER? err = fpQueuePresentKHR(queue, &present); - /*if (err == VK_ERROR_OUT_OF_DATE_KHR) { - // demo->swapchain is out of date (e.g. the window was resized) and - // must be recreated: - // demo_resize(demo); - error("VK_ERROR_OUT_OF_DATE_KHR"); - } - else if (err == VK_SUBOPTIMAL_KHR) { - // demo->swapchain is not as optimal as it could be, but the platform's - // presentation engine will still present the image correctly. - } - else { - assert(!err); - }*/ - assert(!err); - err = vkQueueWaitIdle(queue); assert(err == VK_SUCCESS); vkDestroySemaphore(device, presentCompleteSemaphore, NULL); - if (depthStencil > 0.99f) depthIncrement = -0.001f; - if (depthStencil < 0.8f) depthIncrement = 0.001f; - - depthStencil += depthIncrement; - vkResetCommandBuffer(list->impl._buffer, 0); #ifndef KORE_WINDOWS @@ -348,18 +385,34 @@ void kinc_g5_command_list_end(kinc_g5_command_list_t *list) { void kinc_g5_command_list_clear(kinc_g5_command_list_t *list, struct kinc_g5_render_target *renderTarget, unsigned flags, unsigned color, float depth, int stencil) { - /*VkClearColorValue clearColor = {}; - clearColor.float32[0] = 1.0f; - clearColor.float32[1] = 0.0f; - clearColor.float32[2] = 0.0f; - clearColor.float32[3] = 1.0f; - VkImageSubresourceRange range = {}; - range.levelCount = 1; - range.layerCount = 1; - range.aspectMask = 0; - range.baseArrayLayer = 0; - range.baseMipLevel = 0; - vkCmdClearColorImage(draw_cmd, buffers[current_buffer].image, VK_IMAGE_LAYOUT_GENERAL, &clearColor, 1, &range);*/ + VkClearRect clearRect = {}; + clearRect.rect.offset.x = 0; + clearRect.rect.offset.y = 0; + clearRect.rect.extent.width = renderTarget->width; + clearRect.rect.extent.height = renderTarget->height; + clearRect.baseArrayLayer = 0; + clearRect.layerCount = 1; + + int count = 0; + VkClearAttachment attachments[2]; + if (flags & KINC_G5_CLEAR_COLOR) { + VkClearColorValue clearColor = {}; + clearColor.float32[0] = ((color & 0x00ff0000) >> 16) / 255.0f; + clearColor.float32[1] = ((color & 0x0000ff00) >> 8) / 255.0f; + clearColor.float32[2] = (color & 0x000000ff) / 255.0f; + clearColor.float32[3] = ((color & 0xff000000) >> 24) / 255.0f; + attachments[count].aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + attachments[count].colorAttachment = 0; + attachments[count].clearValue.color = clearColor; + count++; + } + if (((flags & KINC_G5_CLEAR_DEPTH) || (flags & KINC_G5_CLEAR_STENCIL)) && renderTarget->impl.depthBufferBits > 0) { + attachments[count].aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; // | VK_IMAGE_ASPECT_STENCIL_BIT; + attachments[count].clearValue.depthStencil.depth = depth; + attachments[count].clearValue.depthStencil.stencil = stencil; + count++; + } + vkCmdClearAttachments(list->impl._buffer, count, attachments, 1, &clearRect); } void kinc_g5_command_list_render_target_to_framebuffer_barrier(kinc_g5_command_list_t *list, struct kinc_g5_render_target *renderTarget) {} @@ -378,25 +431,55 @@ void kinc_g5_command_list_draw_indexed_vertices_from_to_from(kinc_g5_command_lis vkCmdDrawIndexed(list->impl._buffer, count, 1, start, vertex_offset, 0); } -void kinc_g5_command_list_viewport(kinc_g5_command_list_t *list, int x, int y, int width, int height) {} +void kinc_g5_command_list_viewport(kinc_g5_command_list_t *list, int x, int y, int width, int height) { + VkViewport viewport; + memset(&viewport, 0, sizeof(viewport)); + viewport.x = (float)x; + viewport.y = y + (float)height; + viewport.width = (float)width; + viewport.height = (float)-height; + viewport.minDepth = (float)0.0f; + viewport.maxDepth = (float)1.0f; + vkCmdSetViewport(list->impl._buffer, 0, 1, &viewport); +} -void kinc_g5_command_list_scissor(kinc_g5_command_list_t *list, int x, int y, int width, int height) {} +void kinc_g5_command_list_scissor(kinc_g5_command_list_t *list, int x, int y, int width, int height) { + VkRect2D scissor; + memset(&scissor, 0, sizeof(scissor)); + scissor.extent.width = width; + scissor.extent.height = height; + scissor.offset.x = x; + scissor.offset.y = y; + vkCmdSetScissor(list->impl._buffer, 0, 1, &scissor); +} -void kinc_g5_command_list_disable_scissor(kinc_g5_command_list_t *list) {} +void kinc_g5_command_list_disable_scissor(kinc_g5_command_list_t *list) { + VkRect2D scissor; + memset(&scissor, 0, sizeof(scissor)); + if (currentRenderTargets[0] == nullptr || currentRenderTargets[0]->contextId < 0) { + scissor.extent.width = kinc_width(); + scissor.extent.height = kinc_height(); + } + else { + scissor.extent.width = currentRenderTargets[0]->width; + scissor.extent.height = currentRenderTargets[0]->height; + } + vkCmdSetScissor(list->impl._buffer, 0, 1, &scissor); +} void kinc_g5_command_list_set_pipeline(kinc_g5_command_list_t *list, struct kinc_g5_pipeline *pipeline) { currentPipeline = pipeline; lastVertexConstantBufferOffset = 0; lastFragmentConstantBufferOffset = 0; - vkCmdBindPipeline(list->impl._buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, currentPipeline->impl.pipeline); - - if (vulkanRenderTargets[0] != nullptr) - vkCmdBindDescriptorSets(list->impl._buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, currentPipeline->impl.pipeline_layout, 0, 1, - &vulkanRenderTargets[0]->impl.desc_set, 0, nullptr); - else if (vulkanTextures[0] != nullptr) - vkCmdBindDescriptorSets(list->impl._buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, currentPipeline->impl.pipeline_layout, 0, 1, - &vulkanTextures[0]->impl.desc_set, 0, nullptr); + if (onBackBuffer) { + currentVulkanPipeline = currentPipeline->impl.framebuffer_pipeline; + vkCmdBindPipeline(list->impl._buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, currentPipeline->impl.framebuffer_pipeline); + } + else { + currentVulkanPipeline = currentPipeline->impl.rendertarget_pipeline; + vkCmdBindPipeline(list->impl._buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, currentPipeline->impl.rendertarget_pipeline); + } } void kinc_g5_command_list_set_vertex_buffers(kinc_g5_command_list_t *list, struct kinc_g5_vertex_buffer **vertexBuffers, int *offsets_, int count) { @@ -410,161 +493,222 @@ void kinc_g5_command_list_set_index_buffer(kinc_g5_command_list_t *list, struct vkCmdBindIndexBuffer(list->impl._buffer, indexBuffer->impl.buf, 0, VK_INDEX_TYPE_UINT32); } -void setImageLayout(VkCommandBuffer _buffer, VkImage image, VkImageAspectFlags aspectMask, VkImageLayout oldImageLayout, VkImageLayout newImageLayout); +void kinc_internal_restore_render_target(kinc_g5_command_list_t *list, struct kinc_g5_render_target *target) { + VkViewport viewport; + memset(&viewport, 0, sizeof(viewport)); + viewport.x = 0; + viewport.y = (float)kinc_height(); + viewport.width = (float)kinc_width(); + viewport.height = -(float)kinc_height(); + viewport.minDepth = (float)0.0f; + viewport.maxDepth = (float)1.0f; + vkCmdSetViewport(list->impl._buffer, 0, 1, &viewport); + VkRect2D scissor; + memset(&scissor, 0, sizeof(scissor)); + scissor.extent.width = kinc_width(); + scissor.extent.height = kinc_height(); + scissor.offset.x = 0; + scissor.offset.y = 0; + vkCmdSetScissor(list->impl._buffer, 0, 1, &scissor); -namespace { - kinc_g5_render_target_t *currentRenderTarget = nullptr; - - void endPass(VkCommandBuffer _buffer) { - vkCmdEndRenderPass(_buffer); - - if (currentRenderTarget == nullptr || currentRenderTarget->contextId < 0) { - /*VkImageMemoryBarrier barrier = {}; - barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - barrier.pNext = NULL; - barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; - barrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - barrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; - barrier.image = buffers[current_buffer].image; - - vkCmdPipelineBarrier(draw_cmd, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, NULL, 0, NULL, 1, &barrier);*/ - } - else { - setImageLayout(_buffer, currentRenderTarget->impl.sourceImage, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - setImageLayout(_buffer, currentRenderTarget->impl.destImage, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); - - VkImageBlit imgBlit; - - imgBlit.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imgBlit.srcSubresource.mipLevel = 0; - imgBlit.srcSubresource.baseArrayLayer = 0; - imgBlit.srcSubresource.layerCount = 1; - - imgBlit.srcOffsets[0] = {0, 0, 0}; - imgBlit.srcOffsets[1].x = currentRenderTarget->width; - imgBlit.srcOffsets[1].y = currentRenderTarget->height; - imgBlit.srcOffsets[1].z = 1; - - imgBlit.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - imgBlit.dstSubresource.mipLevel = 0; - imgBlit.dstSubresource.baseArrayLayer = 0; - imgBlit.dstSubresource.layerCount = 1; - - imgBlit.dstOffsets[0] = {0, 0, 0}; - imgBlit.dstOffsets[1].x = currentRenderTarget->width; - imgBlit.dstOffsets[1].y = currentRenderTarget->height; - imgBlit.dstOffsets[1].z = 1; - - vkCmdBlitImage(_buffer, currentRenderTarget->impl.sourceImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, currentRenderTarget->impl.destImage, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &imgBlit, VK_FILTER_LINEAR); - - setImageLayout(_buffer, currentRenderTarget->impl.sourceImage, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - setImageLayout(_buffer, currentRenderTarget->impl.destImage, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - } + if (onBackBuffer) { + return; + } - /*VkResult err = vkEndCommandBuffer(draw_cmd); - assert(!err); + endPass(list); - VkFence nullFence = VK_NULL_HANDLE; - VkPipelineStageFlags pipe_stage_flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.pNext = NULL; - submit_info.waitSemaphoreCount = 1; - submit_info.pWaitSemaphores = &presentCompleteSemaphore; - submit_info.pWaitDstStageMask = &pipe_stage_flags; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = &draw_cmd; - submit_info.signalSemaphoreCount = 0; - submit_info.pSignalSemaphores = NULL; - - err = vkQueueSubmit(queue, 1, &submit_info, nullFence); - assert(!err); + set_barriers(list); - VkCommandBufferInheritanceInfo cmd_buf_hinfo = {}; - cmd_buf_hinfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO; - cmd_buf_hinfo.pNext = NULL; - cmd_buf_hinfo.renderPass = VK_NULL_HANDLE; - cmd_buf_hinfo.subpass = 0; - cmd_buf_hinfo.framebuffer = VK_NULL_HANDLE; - cmd_buf_hinfo.occlusionQueryEnable = VK_FALSE; - cmd_buf_hinfo.queryFlags = 0; - cmd_buf_hinfo.pipelineStatistics = 0; + currentRenderTargets[0] = nullptr; + onBackBuffer = true; - VkCommandBufferBeginInfo cmd_buf_info = {}; - cmd_buf_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - cmd_buf_info.pNext = NULL; - cmd_buf_info.flags = 0; - cmd_buf_info.pInheritanceInfo = &cmd_buf_hinfo; - - VkClearValue clear_values[2]; - memset(clear_values, 0, sizeof(VkClearValue) * 2); - clear_values[0].color.float32[0] = 0.0f; - clear_values[0].color.float32[1] = 0.0f; - clear_values[0].color.float32[2] = 0.0f; - clear_values[0].color.float32[3] = 1.0f; - clear_values[1].depthStencil.depth = depthStencil; - clear_values[1].depthStencil.stencil = 0; + VkClearValue clear_values[2]; + memset(clear_values, 0, sizeof(VkClearValue) * 2); + clear_values[0].color.float32[0] = 0.0f; + clear_values[0].color.float32[1] = 0.0f; + clear_values[0].color.float32[2] = 0.0f; + clear_values[0].color.float32[3] = 1.0f; + clear_values[1].depthStencil.depth = 1.0; + clear_values[1].depthStencil.stencil = 0; + VkRenderPassBeginInfo rp_begin = {}; + rp_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + rp_begin.pNext = nullptr; + rp_begin.renderPass = framebuffer_render_pass; + rp_begin.framebuffer = framebuffers[current_buffer]; + rp_begin.renderArea.offset.x = 0; + rp_begin.renderArea.offset.y = 0; + rp_begin.renderArea.extent.width = kinc_width(); + rp_begin.renderArea.extent.height = kinc_height(); + rp_begin.clearValueCount = 2; + rp_begin.pClearValues = clear_values; + vkCmdBeginRenderPass(list->impl._buffer, &rp_begin, VK_SUBPASS_CONTENTS_INLINE); + currentRenderPassBeginInfo = rp_begin; - VkRenderPassBeginInfo rp_begin = {}; - rp_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - rp_begin.pNext = NULL; - rp_begin.renderPass = render_pass; - rp_begin.framebuffer = framebuffers[current_buffer]; - rp_begin.renderArea.offset.x = 0; - rp_begin.renderArea.offset.y = 0; - rp_begin.renderArea.extent.width = width; - rp_begin.renderArea.extent.height = height; - rp_begin.clearValueCount = 2; - rp_begin.pClearValues = clear_values; - - err = vkBeginCommandBuffer(draw_cmd, &cmd_buf_info); - assert(!err);*/ + if (currentPipeline != NULL) { + currentVulkanPipeline = currentPipeline->impl.framebuffer_pipeline; + vkCmdBindPipeline(list->impl._buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, currentPipeline->impl.framebuffer_pipeline); } } void kinc_g5_command_list_set_render_targets(kinc_g5_command_list_t *list, struct kinc_g5_render_target **targets, int count) { - return; - endPass(list->impl._buffer); + if (targets[0]->contextId < 0) { + kinc_internal_restore_render_target(list, targets[0]); + return; + } + + endPass(list); + + set_barriers(list); - currentRenderTarget = targets[0]; + for (int i = 0; i < count; ++i) { + currentRenderTargets[i] = targets[i]; + } + for (int i = count; i < 8; ++i) { + currentRenderTargets[i] = nullptr; + } onBackBuffer = false; - VkClearValue clear_values[2]; + VkClearValue clear_values[9]; memset(clear_values, 0, sizeof(VkClearValue)); - clear_values[0].color.float32[0] = 0.0f; - clear_values[0].color.float32[1] = 0.0f; - clear_values[0].color.float32[2] = 0.0f; - clear_values[0].color.float32[3] = 1.0f; - clear_values[1].depthStencil.depth = depthStencil; - clear_values[1].depthStencil.stencil = 0; + for (int i = 0; i < count; ++i) { + clear_values[i].color.float32[0] = 0.0f; + clear_values[i].color.float32[1] = 0.0f; + clear_values[i].color.float32[2] = 0.0f; + clear_values[i].color.float32[3] = 1.0f; + } + clear_values[count].depthStencil.depth = 1.0; + clear_values[count].depthStencil.stencil = 0; VkRenderPassBeginInfo rp_begin = {}; rp_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; rp_begin.pNext = nullptr; - rp_begin.renderPass = targets[0]->impl.renderPass; - rp_begin.framebuffer = targets[0]->impl.framebuffer; rp_begin.renderArea.offset.x = 0; rp_begin.renderArea.offset.y = 0; rp_begin.renderArea.extent.width = targets[0]->width; rp_begin.renderArea.extent.height = targets[0]->height; - rp_begin.clearValueCount = 2; + rp_begin.clearValueCount = count + 1; rp_begin.pClearValues = clear_values; + if (count == 1) { + rp_begin.renderPass = rendertarget_render_pass; + rp_begin.framebuffer = targets[0]->impl.framebuffer; + } + else { + VkAttachmentDescription attachments[9]; + for (int i = 0; i < count; ++i) { + attachments[i].format = targets[i]->impl.format; + attachments[i].samples = VK_SAMPLE_COUNT_1_BIT; + attachments[i].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + attachments[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE; + attachments[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachments[i].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attachments[i].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + attachments[i].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + attachments[i].flags = 0; + } + + if (targets[0]->impl.depthBufferBits > 0) { + attachments[count].format = VK_FORMAT_D16_UNORM; + attachments[count].samples = VK_SAMPLE_COUNT_1_BIT; + attachments[count].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + attachments[count].storeOp = VK_ATTACHMENT_STORE_OP_STORE; + attachments[count].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachments[count].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attachments[count].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + attachments[count].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + attachments[count].flags = 0; + } + + VkAttachmentReference color_references[8]; + for (int i = 0; i < count; ++i) { + color_references[i].attachment = i; + color_references[i].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + } + + VkAttachmentReference depth_reference = {}; + depth_reference.attachment = count; + depth_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + VkSubpassDescription subpass = {}; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.flags = 0; + subpass.inputAttachmentCount = 0; + subpass.pInputAttachments = nullptr; + subpass.colorAttachmentCount = count; + subpass.pColorAttachments = color_references; + subpass.pResolveAttachments = nullptr; + subpass.pDepthStencilAttachment = targets[0]->impl.depthBufferBits > 0 ? &depth_reference : nullptr; + subpass.preserveAttachmentCount = 0; + subpass.pPreserveAttachments = nullptr; + + VkSubpassDependency dependencies[2]; + memset(&dependencies, 0, sizeof(dependencies)); + + // TODO: For multi-targets-rendering + dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; + dependencies[0].dstSubpass = 0; + dependencies[0].srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependencies[0].srcAccessMask = VK_ACCESS_SHADER_READ_BIT; + dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + + dependencies[1].srcSubpass = 0; + dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; + dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependencies[1].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dependencies[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + + VkRenderPassCreateInfo rp_info = {}; + rp_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + rp_info.pNext = nullptr; + rp_info.attachmentCount = targets[0]->impl.depthBufferBits > 0 ? count + 1 : count; + rp_info.pAttachments = attachments; + rp_info.subpassCount = 1; + rp_info.pSubpasses = &subpass; + rp_info.dependencyCount = 2; + rp_info.pDependencies = dependencies; + + VkResult err = vkCreateRenderPass(device, &rp_info, NULL, &mrtRenderPass[mrtIndex]); + assert(!err); + + VkImageView attachmentsViews[9]; + for (int i = 0; i < count; ++i) { + attachmentsViews[i] = targets[i]->impl.sourceView; + } + if (targets[0]->impl.depthBufferBits > 0) { + attachmentsViews[count] = targets[0]->impl.depthView; + } + + VkFramebufferCreateInfo fbufCreateInfo = {}; + fbufCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + fbufCreateInfo.pNext = nullptr; + fbufCreateInfo.renderPass = mrtRenderPass[mrtIndex]; + fbufCreateInfo.attachmentCount = targets[0]->impl.depthBufferBits > 0 ? count + 1 : count; + fbufCreateInfo.pAttachments = attachmentsViews; + fbufCreateInfo.width = targets[0]->width; + fbufCreateInfo.height = targets[0]->height; + fbufCreateInfo.layers = 1; + + err = vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &mrtFramebuffer[mrtIndex]); + assert(!err); + + rp_begin.renderPass = mrtRenderPass[mrtIndex]; + rp_begin.framebuffer = mrtFramebuffer[mrtIndex]; + mrtIndex++; + } + vkCmdBeginRenderPass(list->impl._buffer, &rp_begin, VK_SUBPASS_CONTENTS_INLINE); + currentRenderPassBeginInfo = rp_begin; VkViewport viewport; memset(&viewport, 0, sizeof(viewport)); + viewport.x = 0; + viewport.y = (float)targets[0]->height; viewport.width = (float)targets[0]->width; - viewport.height = (float)targets[0]->height; + viewport.height = -(float)targets[0]->height; viewport.minDepth = (float)0.0f; viewport.maxDepth = (float)1.0f; vkCmdSetViewport(list->impl._buffer, 0, 1, &viewport); @@ -576,6 +720,11 @@ void kinc_g5_command_list_set_render_targets(kinc_g5_command_list_t *list, struc scissor.offset.x = 0; scissor.offset.y = 0; vkCmdSetScissor(list->impl._buffer, 0, 1, &scissor); + + if (currentPipeline != NULL) { + currentVulkanPipeline = currentPipeline->impl.rendertarget_pipeline; + vkCmdBindPipeline(list->impl._buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, currentPipeline->impl.rendertarget_pipeline); + } } void kinc_g5_command_list_upload_index_buffer(kinc_g5_command_list_t *list, struct kinc_g5_index_buffer *buffer) {} @@ -584,11 +733,83 @@ void kinc_g5_command_list_upload_vertex_buffer(kinc_g5_command_list_t *list, str void kinc_g5_command_list_upload_texture(kinc_g5_command_list_t *list, struct kinc_g5_texture *texture) {} -void kinc_g5_command_list_get_render_target_pixels(kinc_g5_command_list_t *list, kinc_g5_render_target_t *render_target, uint8_t *data) {} +void kinc_g5_command_list_get_render_target_pixels(kinc_g5_command_list_t *list, kinc_g5_render_target_t *render_target, uint8_t *data) { + VkFormat format = render_target->impl.format; + int formatByteSize = formatSize(format); + + // Create readback buffer + if (!render_target->impl.readbackBufferCreated) { + VkBufferCreateInfo buf_info = {}; + buf_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buf_info.pNext = NULL; + buf_info.size = render_target->width * render_target->height * formatByteSize; + buf_info.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT; + buf_info.flags = 0; + vkCreateBuffer(device, &buf_info, NULL, &render_target->impl.readbackBuffer); + + VkMemoryRequirements mem_reqs = {}; + vkGetBufferMemoryRequirements(device, render_target->impl.readbackBuffer, &mem_reqs); + + VkMemoryAllocateInfo mem_alloc; + memset(&mem_alloc, 0, sizeof(VkMemoryAllocateInfo)); + mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + mem_alloc.pNext = NULL; + mem_alloc.allocationSize = 0; + mem_alloc.memoryTypeIndex = 0; + mem_alloc.allocationSize = mem_reqs.size; + memory_type_from_properties(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &mem_alloc.memoryTypeIndex); + vkAllocateMemory(device, &mem_alloc, NULL, &render_target->impl.readbackMemory); + vkBindBufferMemory(device, render_target->impl.readbackBuffer, render_target->impl.readbackMemory, 0); + + render_target->impl.readbackBufferCreated = true; + } + + vkCmdEndRenderPass(list->impl._buffer); + setImageLayout(list->impl._buffer, render_target->impl.sourceImage, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + + VkBufferImageCopy region; + region.bufferOffset = 0; + region.bufferRowLength = render_target->width; + region.bufferImageHeight = render_target->height; + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.baseArrayLayer = 0; + region.imageSubresource.layerCount = 1; + region.imageSubresource.mipLevel = 0; + region.imageOffset = {0, 0, 0}; + region.imageExtent = {(uint32_t)render_target->width, (uint32_t)render_target->height, 1}; + vkCmdCopyImageToBuffer(list->impl._buffer, render_target->impl.sourceImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, render_target->impl.readbackBuffer, 1, + ®ion); + + setImageLayout(list->impl._buffer, render_target->impl.sourceImage, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + vkCmdBeginRenderPass(list->impl._buffer, ¤tRenderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); + kinc_g5_command_list_execute_and_wait(list); + + // Read buffer + void *p; + vkMapMemory(device, render_target->impl.readbackMemory, 0, VK_WHOLE_SIZE, 0, (void **)&p); + memcpy(data, p, render_target->texWidth * render_target->texHeight * formatByteSize); + vkUnmapMemory(device, render_target->impl.readbackMemory); +} -void kinc_g5_command_list_texture_to_render_target_barrier(kinc_g5_command_list_t *list, struct kinc_g5_render_target *renderTarget) {} +static struct kinc_g5_render_target *texture_to_render_target_barriers[256]; +static int texture_to_render_target_barriers_count = 0; -void kinc_g5_command_list_render_target_to_texture_barrier(kinc_g5_command_list_t *list, struct kinc_g5_render_target *renderTarget) {} +static struct kinc_g5_render_target *render_target_to_texture_barriers[256]; +static int render_target_to_texture_barriers_count = 0; + +// barriers are automatically implemented via the render-passes used by kinc_g5_command_list_set_render_targets +// but doppelt haelt besser +void kinc_g5_command_list_texture_to_render_target_barrier(kinc_g5_command_list_t *list, struct kinc_g5_render_target *renderTarget) { + assert(texture_to_render_target_barriers_count < 256); + texture_to_render_target_barriers[texture_to_render_target_barriers_count++] = renderTarget; +} + +void kinc_g5_command_list_render_target_to_texture_barrier(kinc_g5_command_list_t *list, struct kinc_g5_render_target *renderTarget) { + assert(render_target_to_texture_barriers_count < 256); + render_target_to_texture_barriers[render_target_to_texture_barriers_count++] = renderTarget; +} void kinc_g5_command_list_set_vertex_constant_buffer(kinc_g5_command_list_t *list, struct kinc_g5_constant_buffer *buffer, int offset, size_t size) { lastVertexConstantBufferOffset = offset; @@ -596,12 +817,103 @@ void kinc_g5_command_list_set_vertex_constant_buffer(kinc_g5_command_list_t *lis void kinc_g5_command_list_set_fragment_constant_buffer(kinc_g5_command_list_t *list, struct kinc_g5_constant_buffer *buffer, int offset, size_t size) { lastFragmentConstantBufferOffset = offset; + + VkDescriptorSet descriptor_set = getDescriptorSet(); uint32_t offsets[2] = {lastVertexConstantBufferOffset, lastFragmentConstantBufferOffset}; - vkCmdBindDescriptorSets(list->impl._buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, currentPipeline->impl.pipeline_layout, 0, 1, &desc_set, 2, offsets); + vkCmdBindDescriptorSets(list->impl._buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, currentPipeline->impl.pipeline_layout, 0, 1, &descriptor_set, 2, offsets); +} + +static void set_barriers(kinc_g5_command_list_t *list) { + for (int i = 0; i < texture_to_render_target_barriers_count; ++i) { + VkImageMemoryBarrier barrier = {}; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.pNext = NULL; + barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; + barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + barrier.oldLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.image = texture_to_render_target_barriers[i]->impl.sourceImage; + barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + barrier.subresourceRange.baseMipLevel = 0; + barrier.subresourceRange.levelCount = 1; + barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.layerCount = 1; + vkCmdPipelineBarrier(list->impl._buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, NULL, 0, NULL, 1, &barrier); + } + texture_to_render_target_barriers_count = 0; + + for (int i = 0; i < render_target_to_texture_barriers_count; ++i) { + VkImageMemoryBarrier barrier = {}; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.pNext = NULL; + barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + barrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.image = render_target_to_texture_barriers[i]->impl.sourceImage; + barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + barrier.subresourceRange.baseMipLevel = 0; + barrier.subresourceRange.levelCount = 1; + barrier.subresourceRange.baseArrayLayer = 0; + barrier.subresourceRange.layerCount = 1; + vkCmdPipelineBarrier(list->impl._buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, NULL, 0, NULL, 1, &barrier); + } + render_target_to_texture_barriers_count = 0; } void kinc_g5_command_list_set_pipeline_layout(kinc_g5_command_list_t *list) {} void kinc_g5_command_list_execute(kinc_g5_command_list_t *list) {} -void kinc_g5_command_list_execute_and_wait(kinc_g5_command_list_t *list) {} +void reuse_descriptor_sets(void); + +void kinc_g5_command_list_execute_and_wait(kinc_g5_command_list_t *list) { + vkCmdEndRenderPass(list->impl._buffer); + + VkResult err = vkEndCommandBuffer(list->impl._buffer); + assert(!err); + + VkFence nullFence = {VK_NULL_HANDLE}; + VkSubmitInfo submit_info = {}; + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.pNext = NULL; + submit_info.waitSemaphoreCount = 0; + submit_info.pWaitSemaphores = NULL; + submit_info.pWaitDstStageMask = NULL; + submit_info.commandBufferCount = 1; + submit_info.pCommandBuffers = &list->impl._buffer; + submit_info.signalSemaphoreCount = 0; + submit_info.pSignalSemaphores = NULL; + + err = vkQueueSubmit(queue, 1, &submit_info, nullFence); + assert(!err); + + err = vkQueueWaitIdle(queue); + assert(!err); + + vkResetCommandBuffer(list->impl._buffer, 0); + + reuse_descriptor_sets(); + + VkCommandBufferBeginInfo cmd_buf_info = {}; + cmd_buf_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + cmd_buf_info.pNext = NULL; + cmd_buf_info.flags = 0; + cmd_buf_info.pInheritanceInfo = NULL; + + err = vkBeginCommandBuffer(list->impl._buffer, &cmd_buf_info); + + set_barriers(list); + + vkCmdBeginRenderPass(list->impl._buffer, ¤tRenderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); + + set_viewport_and_scissor(list); + + if (currentPipeline != nullptr) { + vkCmdBindPipeline(list->impl._buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, currentVulkanPipeline); + } +} diff --git a/Backends/Graphics5/Vulkan/Sources/Kore/CommandList5Impl.h b/Backends/Graphics5/Vulkan/Sources/Kore/CommandList5Impl.h index 69ad6f7d6..8d2abb583 100644 --- a/Backends/Graphics5/Vulkan/Sources/Kore/CommandList5Impl.h +++ b/Backends/Graphics5/Vulkan/Sources/Kore/CommandList5Impl.h @@ -1,10 +1,8 @@ #pragma once -#include +#include "MiniVulkan.h" typedef struct { - //Kore::Graphics5::PipelineState* _currentPipeline; int _indexCount; VkCommandBuffer _buffer; - bool closed; } CommandList5Impl; diff --git a/Backends/Graphics5/Vulkan/Sources/Kore/ConstantBuffer5Impl.cpp b/Backends/Graphics5/Vulkan/Sources/Kore/ConstantBuffer5Impl.cpp index 6e30c3482..c42e270f4 100644 --- a/Backends/Graphics5/Vulkan/Sources/Kore/ConstantBuffer5Impl.cpp +++ b/Backends/Graphics5/Vulkan/Sources/Kore/ConstantBuffer5Impl.cpp @@ -13,8 +13,8 @@ bool memory_type_from_properties(uint32_t typeBits, VkFlags requirements_mask, u VkBuffer *Kore::Vulkan::vertexUniformBuffer = nullptr; VkBuffer *Kore::Vulkan::fragmentUniformBuffer = nullptr; -bool kinc_g5_transposeMat3 = true; -bool kinc_g5_transposeMat4 = true; +bool kinc_g5_transposeMat3 = false; +bool kinc_g5_transposeMat4 = false; namespace { void createUniformBuffer(VkBuffer& buf, VkMemoryAllocateInfo& mem_alloc, VkDeviceMemory& mem, VkDescriptorBufferInfo& buffer_info, int size) { diff --git a/Backends/Graphics5/Vulkan/Sources/Kore/ConstantBuffer5Impl.h b/Backends/Graphics5/Vulkan/Sources/Kore/ConstantBuffer5Impl.h index 989fe584e..35971d166 100644 --- a/Backends/Graphics5/Vulkan/Sources/Kore/ConstantBuffer5Impl.h +++ b/Backends/Graphics5/Vulkan/Sources/Kore/ConstantBuffer5Impl.h @@ -1,18 +1,6 @@ #pragma once -#include - -#ifdef min -#undef min -#endif - -#ifdef max -#undef max -#endif - -#ifdef RegisterClass -#undef RegisterClass -#endif +#include "MiniVulkan.h" typedef struct { VkBuffer buf; diff --git a/Backends/Graphics5/Vulkan/Sources/Kore/IndexBuffer5Impl.cpp b/Backends/Graphics5/Vulkan/Sources/Kore/IndexBuffer5Impl.cpp index 386685406..04af58d43 100644 --- a/Backends/Graphics5/Vulkan/Sources/Kore/IndexBuffer5Impl.cpp +++ b/Backends/Graphics5/Vulkan/Sources/Kore/IndexBuffer5Impl.cpp @@ -26,6 +26,9 @@ void kinc_g5_index_buffer_init(kinc_g5_index_buffer_t *buffer, int indexCount, b buf_info.pNext = NULL; buf_info.size = indexCount * sizeof(int); buf_info.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT; +#ifdef KORE_VKRT + buf_info.usage |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; +#endif buf_info.flags = 0; memset(&buffer->impl.mem_alloc, 0, sizeof(VkMemoryAllocateInfo)); @@ -42,12 +45,18 @@ void kinc_g5_index_buffer_init(kinc_g5_index_buffer_t *buffer, int indexCount, b VkMemoryRequirements mem_reqs = {}; vkGetBufferMemoryRequirements(device, buffer->impl.buf, &mem_reqs); - assert(!err); - + buffer->impl.mem_alloc.allocationSize = mem_reqs.size; bool pass = memory_type_from_properties(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &buffer->impl.mem_alloc.memoryTypeIndex); assert(pass); +#ifdef KORE_VKRT + VkMemoryAllocateFlagsInfo memory_allocate_flags_info = {}; + memory_allocate_flags_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO; + memory_allocate_flags_info.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR; + buffer->impl.mem_alloc.pNext = &memory_allocate_flags_info; +#endif + err = vkAllocateMemory(device, &buffer->impl.mem_alloc, NULL, &buffer->impl.mem); assert(!err); diff --git a/Backends/Graphics5/Vulkan/Sources/Kore/IndexBuffer5Impl.h b/Backends/Graphics5/Vulkan/Sources/Kore/IndexBuffer5Impl.h index 8ef89d744..80388adff 100644 --- a/Backends/Graphics5/Vulkan/Sources/Kore/IndexBuffer5Impl.h +++ b/Backends/Graphics5/Vulkan/Sources/Kore/IndexBuffer5Impl.h @@ -1,22 +1,8 @@ #pragma once -#include - -#ifdef min -#undef min -#endif - -#ifdef max -#undef max -#endif - -#ifdef RegisterClass -#undef RegisterClass -#endif +#include "MiniVulkan.h" typedef struct { - //void unset(); - int *data; int myCount; unsigned bufferId; @@ -24,6 +10,4 @@ typedef struct { VkBuffer buf; VkDeviceMemory mem; VkMemoryAllocateInfo mem_alloc; - - //static Graphics5::IndexBuffer* current; } IndexBuffer5Impl; diff --git a/Backends/Graphics5/Vulkan/Sources/Kore/MiniVulkan.h b/Backends/Graphics5/Vulkan/Sources/Kore/MiniVulkan.h new file mode 100644 index 000000000..6c164f633 --- /dev/null +++ b/Backends/Graphics5/Vulkan/Sources/Kore/MiniVulkan.h @@ -0,0 +1,3 @@ +#pragma once + +#include diff --git a/Backends/Graphics5/Vulkan/Sources/Kore/PipelineState5Impl.cpp b/Backends/Graphics5/Vulkan/Sources/Kore/PipelineState5Impl.cpp index d4f2f7071..8021cc895 100644 --- a/Backends/Graphics5/Vulkan/Sources/Kore/PipelineState5Impl.cpp +++ b/Backends/Graphics5/Vulkan/Sources/Kore/PipelineState5Impl.cpp @@ -2,23 +2,27 @@ #include "Vulkan.h" -#include #include +#include #include #include #include -#include #include +#include extern VkDevice device; -extern VkRenderPass render_pass; -extern VkDescriptorSet desc_set; -bool memory_type_from_properties(uint32_t typeBits, VkFlags requirements_mask, uint32_t* typeIndex); -void createDescriptorLayout(PipelineState5Impl* pipeline); +extern VkRenderPass framebuffer_render_pass; +extern VkRenderPass rendertarget_render_pass; +VkDescriptorSetLayout desc_layout; +extern kinc_g5_texture_t *vulkanTextures[16]; +extern kinc_g5_render_target_t *vulkanRenderTargets[16]; +extern uint32_t swapchainImageCount; +extern uint32_t current_buffer; +bool memory_type_from_properties(uint32_t typeBits, VkFlags requirements_mask, uint32_t *typeIndex); -kinc_g5_pipeline_t *currentPipeline = NULL; +static VkDescriptorPool descriptor_pool; static bool has_number(kinc_internal_named_number *named_numbers, const char *name) { for (int i = 0; i < KINC_INTERNAL_NAMED_NUMBER_COUNT; ++i) { @@ -45,7 +49,7 @@ static void set_number(kinc_internal_named_number *named_numbers, const char *na return; } } - + for (int i = 0; i < KINC_INTERNAL_NAMED_NUMBER_COUNT; ++i) { if (named_numbers[i].name[0] == 0) { strcpy(named_numbers[i].name, name); @@ -59,11 +63,7 @@ static void set_number(kinc_internal_named_number *named_numbers, const char *na namespace { void parseShader(kinc_g5_shader_t *shader, kinc_internal_named_number *locations, kinc_internal_named_number *textureBindings, - kinc_internal_named_number *uniformOffsets) { - memset(locations, 0, sizeof(kinc_internal_named_number) * KINC_INTERNAL_NAMED_NUMBER_COUNT); - memset(textureBindings, 0, sizeof(kinc_internal_named_number) * KINC_INTERNAL_NAMED_NUMBER_COUNT); - memset(uniformOffsets, 0, sizeof(kinc_internal_named_number) * KINC_INTERNAL_NAMED_NUMBER_COUNT); - + kinc_internal_named_number *uniformOffsets) { uint32_t *spirv = (uint32_t *)shader->impl.source; int spirvsize = shader->impl.length / 4; int index = 0; @@ -90,7 +90,7 @@ namespace { switch (opcode) { case 5: { // OpName uint32_t id = operands[0]; - char* string = (char*)&operands[1]; + char *string = (char *)&operands[1]; names[id] = string; break; } @@ -98,7 +98,7 @@ namespace { uint32_t type = operands[0]; if (names[type] == "_k_global_uniform_buffer_type") { uint32_t member = operands[1]; - char* string = (char*)&operands[2]; + char *string = (char *)&operands[2]; memberNames[member] = string; } break; @@ -145,7 +145,7 @@ namespace { } } - VkShaderModule demo_prepare_shader_module(const void* code, size_t size) { + VkShaderModule prepare_shader_module(const void *code, size_t size) { VkShaderModuleCreateInfo moduleCreateInfo; VkShaderModule module; VkResult err; @@ -154,7 +154,7 @@ namespace { moduleCreateInfo.pNext = NULL; moduleCreateInfo.codeSize = size; - moduleCreateInfo.pCode = (const uint32_t*)code; + moduleCreateInfo.pCode = (const uint32_t *)code; moduleCreateInfo.flags = 0; err = vkCreateShaderModule(device, &moduleCreateInfo, NULL, &module); assert(!err); @@ -162,25 +162,37 @@ namespace { return module; } - VkShaderModule demo_prepare_vs(VkShaderModule& vert_shader_module, kinc_g5_shader_t *vertexShader) { - vert_shader_module = demo_prepare_shader_module(vertexShader->impl.source, vertexShader->impl.length); + VkShaderModule prepare_vs(VkShaderModule &vert_shader_module, kinc_g5_shader_t *vertexShader) { + vert_shader_module = prepare_shader_module(vertexShader->impl.source, vertexShader->impl.length); return vert_shader_module; } - VkShaderModule demo_prepare_fs(VkShaderModule& frag_shader_module, kinc_g5_shader_t *fragmentShader) { - frag_shader_module = demo_prepare_shader_module(fragmentShader->impl.source, fragmentShader->impl.length); + VkShaderModule prepare_fs(VkShaderModule &frag_shader_module, kinc_g5_shader_t *fragmentShader) { + frag_shader_module = prepare_shader_module(fragmentShader->impl.source, fragmentShader->impl.length); return frag_shader_module; } } +static VkFormat convert_format(kinc_g5_render_target_format_t format) { + switch (format) { + case KINC_G5_RENDER_TARGET_FORMAT_128BIT_FLOAT: + return VK_FORMAT_R32G32B32A32_SFLOAT; + case KINC_G5_RENDER_TARGET_FORMAT_64BIT_FLOAT: + return VK_FORMAT_R16G16B16A16_SFLOAT; + case KINC_G5_RENDER_TARGET_FORMAT_32BIT_RED_FLOAT: + return VK_FORMAT_R32_SFLOAT; + case KINC_G5_RENDER_TARGET_FORMAT_16BIT_RED_FLOAT: + return VK_FORMAT_R16_SFLOAT; + case KINC_G5_RENDER_TARGET_FORMAT_8BIT_RED: + return VK_FORMAT_R8_UNORM; + case KINC_G5_RENDER_TARGET_FORMAT_32BIT: + default: + return VK_FORMAT_B8G8R8A8_UNORM; + } +} + void kinc_g5_pipeline_init(kinc_g5_pipeline_t *pipeline) { - pipeline->vertexShader = nullptr; - pipeline->fragmentShader = nullptr; - pipeline->geometryShader = nullptr; - pipeline->tessellationEvaluationShader = nullptr; - pipeline->tessellationControlShader = nullptr; - createDescriptorLayout(&pipeline->impl); - Kore::Vulkan::createDescriptorSet(&pipeline->impl, nullptr, nullptr, desc_set); + kinc_g5_internal_pipeline_init(pipeline); } void kinc_g5_pipeline_destroy(kinc_g5_pipeline_t *pipeline) {} @@ -204,25 +216,87 @@ kinc_g5_texture_unit_t kinc_g5_pipeline_get_texture_unit(kinc_g5_pipeline_t *pip return unit; } +namespace { + VkCullModeFlagBits convert_cull_mode(kinc_g5_cull_mode_t cullMode) { + switch (cullMode) { + case KINC_G5_CULL_MODE_CLOCKWISE: + return VK_CULL_MODE_BACK_BIT; + case KINC_G5_CULL_MODE_COUNTERCLOCKWISE: + return VK_CULL_MODE_FRONT_BIT; + case KINC_G5_CULL_MODE_NEVER: + default: + return VK_CULL_MODE_NONE; + } + } + + VkCompareOp convert_compare_mode(kinc_g5_compare_mode_t compare) { + switch (compare) { + default: + case KINC_G5_COMPARE_MODE_ALWAYS: + return VK_COMPARE_OP_ALWAYS; + case KINC_G5_COMPARE_MODE_NEVER: + return VK_COMPARE_OP_NEVER; + case KINC_G5_COMPARE_MODE_EQUAL: + return VK_COMPARE_OP_EQUAL; + case KINC_G5_COMPARE_MODE_NOT_EQUAL: + return VK_COMPARE_OP_NOT_EQUAL; + case KINC_G5_COMPARE_MODE_LESS: + return VK_COMPARE_OP_LESS; + case KINC_G5_COMPARE_MODE_LESS_EQUAL: + return VK_COMPARE_OP_LESS_OR_EQUAL; + case KINC_G5_COMPARE_MODE_GREATER: + return VK_COMPARE_OP_GREATER; + case KINC_G5_COMPARE_MODE_GREATER_EQUAL: + return VK_COMPARE_OP_GREATER_OR_EQUAL; + } + } + + VkBlendFactor convert_blend_mode(kinc_g5_blending_operation_t op) { + switch (op) { + default: + case KINC_G5_BLEND_MODE_ONE: + return VK_BLEND_FACTOR_ONE; + case KINC_G5_BLEND_MODE_ZERO: + return VK_BLEND_FACTOR_ZERO; + case KINC_G5_BLEND_MODE_SOURCE_ALPHA: + return VK_BLEND_FACTOR_SRC_ALPHA; + case KINC_G5_BLEND_MODE_DEST_ALPHA: + return VK_BLEND_FACTOR_DST_ALPHA; + case KINC_G5_BLEND_MODE_INV_SOURCE_ALPHA: + return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + case KINC_G5_BLEND_MODE_INV_DEST_ALPHA: + return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA; + case KINC_G5_BLEND_MODE_SOURCE_COLOR: + return VK_BLEND_FACTOR_SRC_COLOR; + case KINC_G5_BLEND_MODE_DEST_COLOR: + return VK_BLEND_FACTOR_DST_COLOR; + case KINC_G5_BLEND_MODE_INV_SOURCE_COLOR: + return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR; + case KINC_G5_BLEND_MODE_INV_DEST_COLOR: + return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR; + } + } +} + void kinc_g5_pipeline_compile(kinc_g5_pipeline_t *pipeline) { + memset(pipeline->impl.vertexLocations, 0, sizeof(kinc_internal_named_number) * KINC_INTERNAL_NAMED_NUMBER_COUNT); + memset(pipeline->impl.vertexOffsets, 0, sizeof(kinc_internal_named_number) * KINC_INTERNAL_NAMED_NUMBER_COUNT); + memset(pipeline->impl.fragmentLocations, 0, sizeof(kinc_internal_named_number) * KINC_INTERNAL_NAMED_NUMBER_COUNT); + memset(pipeline->impl.fragmentOffsets, 0, sizeof(kinc_internal_named_number) * KINC_INTERNAL_NAMED_NUMBER_COUNT); + memset(pipeline->impl.textureBindings, 0, sizeof(kinc_internal_named_number) * KINC_INTERNAL_NAMED_NUMBER_COUNT); parseShader(pipeline->vertexShader, pipeline->impl.vertexLocations, pipeline->impl.textureBindings, pipeline->impl.vertexOffsets); parseShader(pipeline->fragmentShader, pipeline->impl.fragmentLocations, pipeline->impl.textureBindings, pipeline->impl.fragmentOffsets); - // - VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo = {}; pPipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; pPipelineLayoutCreateInfo.pNext = NULL; pPipelineLayoutCreateInfo.setLayoutCount = 1; - pPipelineLayoutCreateInfo.pSetLayouts = &pipeline->impl.desc_layout; + pPipelineLayoutCreateInfo.pSetLayouts = &desc_layout; VkResult err = vkCreatePipelineLayout(device, &pPipelineLayoutCreateInfo, NULL, &pipeline->impl.pipeline_layout); assert(!err); - // - VkGraphicsPipelineCreateInfo pipeline_info = {}; - VkPipelineCacheCreateInfo pipelineCache_info = {}; VkPipelineInputAssemblyStateCreateInfo ia = {}; VkPipelineRasterizationStateCreateInfo rs = {}; @@ -230,11 +304,12 @@ void kinc_g5_pipeline_compile(kinc_g5_pipeline_t *pipeline) { VkPipelineDepthStencilStateCreateInfo ds = {}; VkPipelineViewportStateCreateInfo vp = {}; VkPipelineMultisampleStateCreateInfo ms = {}; - VkDynamicState dynamicStateEnables[VK_DYNAMIC_STATE_RANGE_SIZE]; + const int dynamicStatesCount = 2; + VkDynamicState dynamicStateEnables[dynamicStatesCount]; VkPipelineDynamicStateCreateInfo dynamicState = {}; - memset(dynamicStateEnables, 0, sizeof dynamicStateEnables); - memset(&dynamicState, 0, sizeof dynamicState); + memset(dynamicStateEnables, 0, sizeof(dynamicStateEnables)); + memset(&dynamicState, 0, sizeof(dynamicState)); dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; dynamicState.pDynamicStates = dynamicStateEnables; @@ -264,12 +339,19 @@ void kinc_g5_pipeline_compile(kinc_g5_pipeline_t *pipeline) { case KINC_G4_VERTEX_DATA_FLOAT4X4: stride += 4 * 4 * 4; break; + case KINC_G4_VERTEX_DATA_SHORT2_NORM: + stride += 2 * 2; + break; + case KINC_G4_VERTEX_DATA_SHORT4_NORM: + stride += 4 * 2; + break; } } VkVertexInputBindingDescription vi_bindings[1]; #ifdef KORE_WINDOWS - VkVertexInputAttributeDescription* vi_attrs = (VkVertexInputAttributeDescription*)alloca(sizeof(VkVertexInputAttributeDescription) * pipeline->inputLayout[0]->size); + VkVertexInputAttributeDescription *vi_attrs = + (VkVertexInputAttributeDescription *)alloca(sizeof(VkVertexInputAttributeDescription) * pipeline->inputLayout[0]->size); #else VkVertexInputAttributeDescription vi_attrs[pipeline->inputLayout[0]->size]; #endif @@ -332,6 +414,20 @@ void kinc_g5_pipeline_compile(kinc_g5_pipeline_t *pipeline) { vi_attrs[i].offset = offset; offset += 4 * 4 * 4; break; + case KINC_G4_VERTEX_DATA_SHORT2_NORM: + vi_attrs[i].binding = 0; + vi_attrs[i].location = find_number(pipeline->impl.vertexLocations, element.name); + vi_attrs[i].format = VK_FORMAT_R16G16_SNORM; + vi_attrs[i].offset = offset; + offset += 2 * 2; + break; + case KINC_G4_VERTEX_DATA_SHORT4_NORM: + vi_attrs[i].binding = 0; + vi_attrs[i].location = find_number(pipeline->impl.vertexLocations, element.name); + vi_attrs[i].format = VK_FORMAT_R16G16B16A16_SNORM; + vi_attrs[i].offset = offset; + offset += 4 * 2; + break; } } @@ -342,8 +438,8 @@ void kinc_g5_pipeline_compile(kinc_g5_pipeline_t *pipeline) { memset(&rs, 0, sizeof(rs)); rs.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; rs.polygonMode = VK_POLYGON_MODE_FILL; - rs.cullMode = VK_CULL_MODE_NONE; - rs.frontFace = VK_FRONT_FACE_CLOCKWISE; + rs.cullMode = convert_cull_mode(pipeline->cullMode); + rs.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; rs.depthClampEnable = VK_FALSE; rs.rasterizerDiscardEnable = VK_FALSE; rs.depthBiasEnable = VK_FALSE; @@ -351,11 +447,22 @@ void kinc_g5_pipeline_compile(kinc_g5_pipeline_t *pipeline) { memset(&cb, 0, sizeof(cb)); cb.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; - VkPipelineColorBlendAttachmentState att_state[1]; + VkPipelineColorBlendAttachmentState att_state[8]; memset(att_state, 0, sizeof(att_state)); - att_state[0].colorWriteMask = 0xf; - att_state[0].blendEnable = VK_FALSE; - cb.attachmentCount = 1; + for (int i = 0; i < pipeline->colorAttachmentCount; ++i) { + att_state[i].colorWriteMask = + (pipeline->colorWriteMaskRed[i] ? VK_COLOR_COMPONENT_R_BIT : 0) | (pipeline->colorWriteMaskGreen[i] ? VK_COLOR_COMPONENT_G_BIT : 0) | + (pipeline->colorWriteMaskBlue[i] ? VK_COLOR_COMPONENT_B_BIT : 0) | (pipeline->colorWriteMaskAlpha[i] ? VK_COLOR_COMPONENT_A_BIT : 0); + att_state[i].blendEnable = pipeline->blendSource != KINC_G5_BLEND_MODE_ONE || pipeline->blendDestination != KINC_G5_BLEND_MODE_ZERO || + pipeline->alphaBlendSource != KINC_G5_BLEND_MODE_ONE || pipeline->alphaBlendDestination != KINC_G5_BLEND_MODE_ZERO; + att_state[i].srcColorBlendFactor = convert_blend_mode(pipeline->blendSource); + att_state[i].dstColorBlendFactor = convert_blend_mode(pipeline->blendDestination); + att_state[i].colorBlendOp = VK_BLEND_OP_ADD; + att_state[i].srcAlphaBlendFactor = convert_blend_mode(pipeline->alphaBlendSource); + att_state[i].dstAlphaBlendFactor = convert_blend_mode(pipeline->alphaBlendDestination); + att_state[i].alphaBlendOp = VK_BLEND_OP_ADD; + } + cb.attachmentCount = pipeline->colorAttachmentCount; cb.pAttachments = att_state; memset(&vp, 0, sizeof(vp)); @@ -367,9 +474,9 @@ void kinc_g5_pipeline_compile(kinc_g5_pipeline_t *pipeline) { memset(&ds, 0, sizeof(ds)); ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; - ds.depthTestEnable = VK_FALSE; - ds.depthWriteEnable = VK_FALSE; - ds.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL; + ds.depthTestEnable = pipeline->depthMode != KINC_G5_COMPARE_MODE_ALWAYS; + ds.depthWriteEnable = pipeline->depthWrite; + ds.depthCompareOp = convert_compare_mode(pipeline->depthMode); ds.depthBoundsTestEnable = VK_FALSE; ds.back.failOp = VK_STENCIL_OP_KEEP; ds.back.passOp = VK_STENCIL_OP_KEEP; @@ -388,14 +495,14 @@ void kinc_g5_pipeline_compile(kinc_g5_pipeline_t *pipeline) { shaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; - shaderStages[0].module = demo_prepare_vs(pipeline->impl.vert_shader_module, pipeline->vertexShader); + shaderStages[0].module = prepare_vs(pipeline->impl.vert_shader_module, pipeline->vertexShader); shaderStages[0].pName = "main"; shaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; - shaderStages[1].module = demo_prepare_fs(pipeline->impl.frag_shader_module, pipeline->fragmentShader); + shaderStages[1].module = prepare_fs(pipeline->impl.frag_shader_module, pipeline->fragmentShader); shaderStages[1].pName = "main"; - + pipeline_info.pVertexInputState = &vi; pipeline_info.pInputAssemblyState = &ia; pipeline_info.pRasterizationState = &rs; @@ -404,27 +511,23 @@ void kinc_g5_pipeline_compile(kinc_g5_pipeline_t *pipeline) { pipeline_info.pViewportState = &vp; pipeline_info.pDepthStencilState = &ds; pipeline_info.pStages = shaderStages; - pipeline_info.renderPass = render_pass; + pipeline_info.renderPass = framebuffer_render_pass; pipeline_info.pDynamicState = &dynamicState; - memset(&pipelineCache_info, 0, sizeof(pipelineCache_info)); - pipelineCache_info.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; - - err = vkCreatePipelineCache(device, &pipelineCache_info, nullptr, &pipeline->impl.pipelineCache); - assert(!err); - err = vkCreateGraphicsPipelines(device, pipeline->impl.pipelineCache, 1, &pipeline_info, nullptr, &pipeline->impl.pipeline); + err = vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipeline_info, NULL, &pipeline->impl.framebuffer_pipeline); assert(!err); - vkDestroyPipelineCache(device, pipeline->impl.pipelineCache, nullptr); + pipeline_info.renderPass = rendertarget_render_pass; + + err = vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipeline_info, NULL, &pipeline->impl.rendertarget_pipeline); + assert(!err); vkDestroyShaderModule(device, pipeline->impl.frag_shader_module, nullptr); vkDestroyShaderModule(device, pipeline->impl.vert_shader_module, nullptr); } -extern VkDescriptorPool desc_pool; - -void createDescriptorLayout(PipelineState5Impl* pipeline) { - VkDescriptorSetLayoutBinding layoutBindings[8]; +void createDescriptorLayout() { + VkDescriptorSetLayoutBinding layoutBindings[18]; memset(layoutBindings, 0, sizeof(layoutBindings)); layoutBindings[0].binding = 0; @@ -439,126 +542,245 @@ void createDescriptorLayout(PipelineState5Impl* pipeline) { layoutBindings[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; layoutBindings[1].pImmutableSamplers = nullptr; - for (int i = 2; i < 8; ++i) { + for (int i = 2; i < 18; ++i) { layoutBindings[i].binding = i; layoutBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; layoutBindings[i].descriptorCount = 1; - layoutBindings[i].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + layoutBindings[i].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_VERTEX_BIT; layoutBindings[i].pImmutableSamplers = nullptr; } VkDescriptorSetLayoutCreateInfo descriptor_layout = {}; descriptor_layout.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; descriptor_layout.pNext = NULL; - descriptor_layout.bindingCount = 8; + descriptor_layout.bindingCount = 18; descriptor_layout.pBindings = layoutBindings; - VkResult err = vkCreateDescriptorSetLayout(device, &descriptor_layout, NULL, &pipeline->desc_layout); + VkResult err = vkCreateDescriptorSetLayout(device, &descriptor_layout, NULL, &desc_layout); assert(!err); - VkDescriptorPoolSize typeCounts[8]; + VkDescriptorPoolSize typeCounts[2]; memset(typeCounts, 0, sizeof(typeCounts)); typeCounts[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; - typeCounts[0].descriptorCount = 1; + typeCounts[0].descriptorCount = 2 * 1024; + + typeCounts[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + typeCounts[1].descriptorCount = 16 * 1024; + + VkDescriptorPoolCreateInfo pool_info = {}; + pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + pool_info.pNext = NULL; + pool_info.maxSets = 1024; + pool_info.poolSizeCount = 2; + pool_info.pPoolSizes = typeCounts; + + err = vkCreateDescriptorPool(device, &pool_info, NULL, &descriptor_pool); + assert(!err); +} - typeCounts[1].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; - typeCounts[1].descriptorCount = 1; +int calc_descriptor_id(void) { + int texture_count = 0; + for (int i = 0; i < 16; ++i) { + if (vulkanTextures[i] != nullptr) { + texture_count++; + } + else if (vulkanRenderTargets[i] != nullptr) { + texture_count++; + } + } + + bool uniform_buffer = Kore::Vulkan::vertexUniformBuffer != nullptr && Kore::Vulkan::fragmentUniformBuffer != nullptr; + + return 1 | (texture_count << 1) | ((uniform_buffer ? 1 : 0) << 8); +} + +#define MAX_DESCRIPTOR_SETS 256 + +struct destriptor_set { + int id; + bool in_use; + VkDescriptorSet set; +}; + +static struct destriptor_set descriptor_sets[MAX_DESCRIPTOR_SETS] = {0}; +static int descriptor_sets_count = 0; + +extern bool kinc_vulkan_internal_bilinear; + +static void update_textures(VkDescriptorSet descriptor_set) { + VkDescriptorImageInfo tex_desc[16]; + memset(&tex_desc, 0, sizeof(tex_desc)); - for (int i = 2; i < 8; ++i) { - typeCounts[i].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - typeCounts[i].descriptorCount = 1; + int texture_count = 0; + for (int i = 0; i < 16; ++i) { + if (vulkanTextures[i] != NULL) { + if (kinc_vulkan_internal_bilinear) { + tex_desc[i].sampler = vulkanTextures[i]->impl.texture.bilinear_sampler; + } + else { + tex_desc[i].sampler = vulkanTextures[i]->impl.texture.point_sampler; + } + tex_desc[i].imageView = vulkanTextures[i]->impl.texture.view; + texture_count++; + } + else if (vulkanRenderTargets[i] != NULL) { + if (kinc_vulkan_internal_bilinear) { + tex_desc[i].sampler = vulkanRenderTargets[i]->impl.bilinear_sampler; + } + else { + tex_desc[i].sampler = vulkanRenderTargets[i]->impl.point_sampler; + } + if (vulkanRenderTargets[i]->impl.stage_depth == i) { + tex_desc[i].imageView = vulkanRenderTargets[i]->impl.depthView; + vulkanRenderTargets[i]->impl.stage_depth = -1; + } + else { + tex_desc[i].imageView = vulkanRenderTargets[i]->impl.sourceView; + } + texture_count++; + } + tex_desc[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; } - VkDescriptorPoolCreateInfo descriptor_pool = {}; - descriptor_pool.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; - descriptor_pool.pNext = NULL; - descriptor_pool.maxSets = 128; - descriptor_pool.poolSizeCount = 8; - descriptor_pool.pPoolSizes = typeCounts; + VkWriteDescriptorSet writes[16]; + memset(&writes, 0, sizeof(writes)); - err = vkCreateDescriptorPool(device, &descriptor_pool, NULL, &desc_pool); - assert(!err); + for (int i = 0; i < 16; ++i) { + writes[i].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + writes[i].dstSet = descriptor_set; + writes[i].dstBinding = i + 2; + writes[i].descriptorCount = 1; + writes[i].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + writes[i].pImageInfo = &tex_desc[i]; + } + + if (vulkanTextures[0] != NULL || vulkanRenderTargets[0] != NULL) { + vkUpdateDescriptorSets(device, texture_count, writes, 0, NULL); + } } -void Kore::Vulkan::createDescriptorSet(struct PipelineState5Impl_s *pipeline, kinc_g5_texture_t *texture, kinc_g5_render_target_t *renderTarget, - VkDescriptorSet &desc_set) { - // VkDescriptorImageInfo tex_descs[DEMO_TEXTURE_COUNT]; - VkDescriptorBufferInfo buffer_descs[2]; +void reuse_descriptor_sets(void) { + for (int i = 0; i < descriptor_sets_count; ++i) { + descriptor_sets[i].in_use = false; + } +} + +VkDescriptorSet getDescriptorSet() { + int id = calc_descriptor_id(); + for (int i = 0; i < descriptor_sets_count; ++i) { + if (!descriptor_sets[i].in_use && descriptor_sets[i].id == id) { + descriptor_sets[i].in_use = true; + update_textures(descriptor_sets[i].set); + return descriptor_sets[i].set; + } + } VkDescriptorSetAllocateInfo alloc_info = {}; alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; alloc_info.pNext = NULL; - alloc_info.descriptorPool = desc_pool; + alloc_info.descriptorPool = descriptor_pool; alloc_info.descriptorSetCount = 1; - alloc_info.pSetLayouts = &pipeline->desc_layout; - VkResult err = vkAllocateDescriptorSets(device, &alloc_info, &desc_set); + alloc_info.pSetLayouts = &desc_layout; + VkDescriptorSet descriptor_set; + VkResult err = vkAllocateDescriptorSets(device, &alloc_info, &descriptor_set); assert(!err); + VkDescriptorBufferInfo buffer_descs[2]; + memset(&buffer_descs, 0, sizeof(buffer_descs)); - if (vertexUniformBuffer != nullptr) { - buffer_descs[0].buffer = *vertexUniformBuffer; + if (Kore::Vulkan::vertexUniformBuffer != nullptr) { + buffer_descs[0].buffer = *Kore::Vulkan::vertexUniformBuffer; } buffer_descs[0].offset = 0; buffer_descs[0].range = 256 * sizeof(float); - if (fragmentUniformBuffer != nullptr) { - buffer_descs[1].buffer = *fragmentUniformBuffer; + if (Kore::Vulkan::fragmentUniformBuffer != nullptr) { + buffer_descs[1].buffer = *Kore::Vulkan::fragmentUniformBuffer; } buffer_descs[1].offset = 0; buffer_descs[1].range = 256 * sizeof(float); - VkDescriptorImageInfo tex_desc; + VkDescriptorImageInfo tex_desc[16]; memset(&tex_desc, 0, sizeof(tex_desc)); - if (texture != nullptr) { - tex_desc.sampler = texture->impl.texture.sampler; - tex_desc.imageView = texture->impl.texture.view; - } - if (renderTarget != nullptr) { - tex_desc.sampler = renderTarget->impl.sampler; - tex_desc.imageView = renderTarget->impl.destView; + int texture_count = 0; + for (int i = 0; i < 16; ++i) { + if (vulkanTextures[i] != nullptr) { + if (kinc_vulkan_internal_bilinear) { + tex_desc[i].sampler = vulkanTextures[i]->impl.texture.bilinear_sampler; + } + else { + tex_desc[i].sampler = vulkanTextures[i]->impl.texture.point_sampler; + } + tex_desc[i].imageView = vulkanTextures[i]->impl.texture.view; + texture_count++; + } + else if (vulkanRenderTargets[i] != nullptr) { + if (kinc_vulkan_internal_bilinear) { + tex_desc[i].sampler = vulkanRenderTargets[i]->impl.bilinear_sampler; + } + else { + tex_desc[i].sampler = vulkanRenderTargets[i]->impl.point_sampler; + } + if (vulkanRenderTargets[i]->impl.stage_depth == i) { + tex_desc[i].imageView = vulkanRenderTargets[i]->impl.depthView; + vulkanRenderTargets[i]->impl.stage_depth = -1; + } + else { + tex_desc[i].imageView = vulkanRenderTargets[i]->impl.sourceView; + } + texture_count++; + } + tex_desc[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; } - tex_desc.imageLayout = VK_IMAGE_LAYOUT_GENERAL; - VkWriteDescriptorSet writes[8]; - memset(writes, 0, sizeof(writes)); + VkWriteDescriptorSet writes[18]; + memset(&writes, 0, sizeof(writes)); writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writes[0].dstSet = desc_set; + writes[0].dstSet = descriptor_set; writes[0].dstBinding = 0; writes[0].descriptorCount = 1; writes[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; writes[0].pBufferInfo = &buffer_descs[0]; writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writes[1].dstSet = desc_set; + writes[1].dstSet = descriptor_set; writes[1].dstBinding = 1; writes[1].descriptorCount = 1; writes[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; writes[1].pBufferInfo = &buffer_descs[1]; - for (int i = 2; i < 8; ++i) { + for (int i = 2; i < 18; ++i) { writes[i].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writes[i].dstSet = desc_set; + writes[i].dstSet = descriptor_set; writes[i].dstBinding = i; writes[i].descriptorCount = 1; writes[i].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - writes[i].pImageInfo = &tex_desc; + writes[i].pImageInfo = &tex_desc[i - 2]; } - if (texture != nullptr || renderTarget != nullptr) { - if (vertexUniformBuffer != nullptr && fragmentUniformBuffer != nullptr) { - vkUpdateDescriptorSets(device, 3, writes, 0, nullptr); + if (vulkanTextures[0] != nullptr || vulkanRenderTargets[0] != nullptr) { + if (Kore::Vulkan::vertexUniformBuffer != nullptr && Kore::Vulkan::fragmentUniformBuffer != nullptr) { + vkUpdateDescriptorSets(device, 2 + texture_count, writes, 0, nullptr); } else { - vkUpdateDescriptorSets(device, 1, writes + 2, 0, nullptr); + vkUpdateDescriptorSets(device, texture_count, writes + 2, 0, nullptr); } } else { - if (vertexUniformBuffer != nullptr && fragmentUniformBuffer != nullptr) { + if (Kore::Vulkan::vertexUniformBuffer != nullptr && Kore::Vulkan::fragmentUniformBuffer != nullptr) { vkUpdateDescriptorSets(device, 2, writes, 0, nullptr); } } + + assert(descriptor_sets_count + 1 < MAX_DESCRIPTOR_SETS); + descriptor_sets[descriptor_sets_count].id = id; + descriptor_sets[descriptor_sets_count].in_use = true; + descriptor_sets[descriptor_sets_count].set = descriptor_set; + descriptor_sets_count += 1; + + return descriptor_set; } diff --git a/Backends/Graphics5/Vulkan/Sources/Kore/PipelineState5Impl.h b/Backends/Graphics5/Vulkan/Sources/Kore/PipelineState5Impl.h index 467537f6d..a20468e94 100644 --- a/Backends/Graphics5/Vulkan/Sources/Kore/PipelineState5Impl.h +++ b/Backends/Graphics5/Vulkan/Sources/Kore/PipelineState5Impl.h @@ -1,18 +1,6 @@ #pragma once -#include - -#ifdef min -#undef min -#endif - -#ifdef max -#undef max -#endif - -#ifdef RegisterClass -#undef RegisterClass -#endif +#include "MiniVulkan.h" struct kinc_g5_shader; @@ -24,12 +12,12 @@ typedef struct { } kinc_internal_named_number; typedef struct PipelineState5Impl_s { - const char** textures; - int* textureValues; + const char **textures; + int *textureValues; int textureCount; - VkPipeline pipeline; - VkPipelineCache pipelineCache; + VkPipeline framebuffer_pipeline; + VkPipeline rendertarget_pipeline; VkShaderModule vert_shader_module; VkShaderModule frag_shader_module; @@ -40,10 +28,6 @@ typedef struct PipelineState5Impl_s { kinc_internal_named_number fragmentOffsets[KINC_INTERNAL_NAMED_NUMBER_COUNT]; VkPipelineLayout pipeline_layout; - - VkDescriptorSetLayout desc_layout; - - //static Graphics5::PipelineState* current; } PipelineState5Impl; typedef struct { diff --git a/Backends/Graphics5/Vulkan/Sources/Kore/RayTraceImpl.cpp b/Backends/Graphics5/Vulkan/Sources/Kore/RayTraceImpl.cpp new file mode 100644 index 000000000..8ce70cd0d --- /dev/null +++ b/Backends/Graphics5/Vulkan/Sources/Kore/RayTraceImpl.cpp @@ -0,0 +1,750 @@ +#include "pch.h" + +#include "RayTraceImpl.h" + +#ifdef KORE_VKRT + +#include "Vulkan.h" +#include +#include +#include +#include +#include +#include +#include +#include + +extern VkDevice device; +extern VkQueue queue; +extern VkCommandPool cmd_pool; +extern VkPhysicalDevice gpu; +extern VkRenderPassBeginInfo currentRenderPassBeginInfo; +extern VkFramebuffer *framebuffers; +extern uint32_t current_buffer; +bool memory_type_from_properties(uint32_t typeBits, VkFlags requirements_mask, uint32_t* typeIndex); + +const int INDEX_RAYGEN = 0; +const int INDEX_CLOSEST_HIT = 1; +const int INDEX_MISS = 2; +const char* raygen_shader_name = "raygeneration"; +const char* closesthit_shader_name = "closesthit"; +const char* miss_shader_name = "miss"; + +VkDescriptorPool descriptor_pool; +kinc_raytrace_acceleration_structure_t* accel; +kinc_raytrace_pipeline_t* pipeline; +kinc_g5_texture_t* output = nullptr; + +void kinc_raytrace_pipeline_init(kinc_raytrace_pipeline_t *pipeline, kinc_g5_command_list *command_list, void *ray_shader, int ray_shader_size, kinc_g5_constant_buffer_t *constant_buffer) { + pipeline->_constant_buffer = constant_buffer; + + { + VkDescriptorSetLayoutBinding acceleration_structure_layout_binding{}; + acceleration_structure_layout_binding.binding = 0; + acceleration_structure_layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; + acceleration_structure_layout_binding.descriptorCount = 1; + acceleration_structure_layout_binding.stageFlags = VK_SHADER_STAGE_RAYGEN_BIT_KHR; + + VkDescriptorSetLayoutBinding result_image_layout_binding{}; + result_image_layout_binding.binding = 1; + result_image_layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + result_image_layout_binding.descriptorCount = 1; + result_image_layout_binding.stageFlags = VK_SHADER_STAGE_RAYGEN_BIT_KHR; + + VkDescriptorSetLayoutBinding uniform_buffer_binding{}; + uniform_buffer_binding.binding = 2; + uniform_buffer_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + uniform_buffer_binding.descriptorCount = 1; + uniform_buffer_binding.stageFlags = VK_SHADER_STAGE_RAYGEN_BIT_KHR; + + VkDescriptorSetLayoutBinding bindings[3] = { acceleration_structure_layout_binding, result_image_layout_binding, uniform_buffer_binding }; + + VkDescriptorSetLayoutCreateInfo layout_info{}; + layout_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + layout_info.pNext = NULL; + layout_info.bindingCount = 3; + layout_info.pBindings = &bindings[0]; + vkCreateDescriptorSetLayout(device, &layout_info, nullptr, &pipeline->impl.descriptor_set_layout); + + VkPipelineLayoutCreateInfo pipeline_layout_create_info{}; + pipeline_layout_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + pipeline_layout_create_info.pNext = NULL; + pipeline_layout_create_info.setLayoutCount = 1; + pipeline_layout_create_info.pSetLayouts = &pipeline->impl.descriptor_set_layout; + + vkCreatePipelineLayout(device, &pipeline_layout_create_info, nullptr, &pipeline->impl.pipeline_layout); + + VkShaderModuleCreateInfo module_create_info{}; + memset(&module_create_info, 0, sizeof(VkShaderModuleCreateInfo)); + module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + module_create_info.codeSize = ray_shader_size; + module_create_info.pCode = (const uint32_t *)ray_shader; + module_create_info.pNext = nullptr; + module_create_info.flags = 0; + VkShaderModule shader_module; + vkCreateShaderModule(device, &module_create_info, NULL, &shader_module); + + VkPipelineShaderStageCreateInfo shader_stages[3]; + shader_stages[INDEX_RAYGEN].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + shader_stages[INDEX_RAYGEN].pNext = NULL; + shader_stages[INDEX_RAYGEN].stage = VK_SHADER_STAGE_RAYGEN_BIT_KHR; + shader_stages[INDEX_RAYGEN].module = shader_module; + shader_stages[INDEX_RAYGEN].pName = raygen_shader_name; + shader_stages[INDEX_RAYGEN].flags = 0; + shader_stages[INDEX_RAYGEN].pSpecializationInfo = NULL; + + shader_stages[INDEX_CLOSEST_HIT].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + shader_stages[INDEX_CLOSEST_HIT].pNext = NULL; + shader_stages[INDEX_CLOSEST_HIT].stage = VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR; + shader_stages[INDEX_CLOSEST_HIT].module = shader_module; + shader_stages[INDEX_CLOSEST_HIT].pName = closesthit_shader_name; + shader_stages[INDEX_CLOSEST_HIT].flags = 0; + shader_stages[INDEX_CLOSEST_HIT].pSpecializationInfo = NULL; + + shader_stages[INDEX_MISS].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + shader_stages[INDEX_MISS].pNext = NULL; + shader_stages[INDEX_MISS].stage = VK_SHADER_STAGE_MISS_BIT_KHR; + shader_stages[INDEX_MISS].module = shader_module; + shader_stages[INDEX_MISS].pName = miss_shader_name; + shader_stages[INDEX_MISS].flags = 0; + shader_stages[INDEX_MISS].pSpecializationInfo = NULL; + + VkRayTracingShaderGroupCreateInfoKHR groups[3]; + groups[INDEX_RAYGEN].sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; + groups[INDEX_RAYGEN].pNext = NULL; + groups[INDEX_RAYGEN].generalShader = VK_SHADER_UNUSED_KHR; + groups[INDEX_RAYGEN].closestHitShader = VK_SHADER_UNUSED_KHR; + groups[INDEX_RAYGEN].anyHitShader = VK_SHADER_UNUSED_KHR; + groups[INDEX_RAYGEN].intersectionShader = VK_SHADER_UNUSED_KHR; + groups[INDEX_RAYGEN].type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; + groups[INDEX_RAYGEN].generalShader = INDEX_RAYGEN; + + groups[INDEX_CLOSEST_HIT].sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; + groups[INDEX_CLOSEST_HIT].pNext = NULL; + groups[INDEX_CLOSEST_HIT].generalShader = VK_SHADER_UNUSED_KHR; + groups[INDEX_CLOSEST_HIT].closestHitShader = VK_SHADER_UNUSED_KHR; + groups[INDEX_CLOSEST_HIT].anyHitShader = VK_SHADER_UNUSED_KHR; + groups[INDEX_CLOSEST_HIT].intersectionShader = VK_SHADER_UNUSED_KHR; + groups[INDEX_CLOSEST_HIT].type = VK_RAY_TRACING_SHADER_GROUP_TYPE_TRIANGLES_HIT_GROUP_KHR; + groups[INDEX_CLOSEST_HIT].closestHitShader = INDEX_CLOSEST_HIT; + + groups[INDEX_MISS].sType = VK_STRUCTURE_TYPE_RAY_TRACING_SHADER_GROUP_CREATE_INFO_KHR; + groups[INDEX_MISS].pNext = NULL; + groups[INDEX_MISS].generalShader = VK_SHADER_UNUSED_KHR; + groups[INDEX_MISS].closestHitShader = VK_SHADER_UNUSED_KHR; + groups[INDEX_MISS].anyHitShader = VK_SHADER_UNUSED_KHR; + groups[INDEX_MISS].intersectionShader = VK_SHADER_UNUSED_KHR; + groups[INDEX_MISS].type = VK_RAY_TRACING_SHADER_GROUP_TYPE_GENERAL_KHR; + groups[INDEX_MISS].generalShader = INDEX_MISS; + + VkRayTracingPipelineCreateInfoKHR raytracing_pipeline_create_info = {}; + raytracing_pipeline_create_info.sType = VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR; + raytracing_pipeline_create_info.pNext = NULL; + raytracing_pipeline_create_info.flags = 0; + raytracing_pipeline_create_info.stageCount = 3; + raytracing_pipeline_create_info.pStages = &shader_stages[0]; + raytracing_pipeline_create_info.groupCount = 3; + raytracing_pipeline_create_info.pGroups = &groups[0]; + raytracing_pipeline_create_info.maxRecursionDepth = 1; + raytracing_pipeline_create_info.layout = pipeline->impl.pipeline_layout; + raytracing_pipeline_create_info.libraries.sType = VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR; + raytracing_pipeline_create_info.libraries.libraryCount = 0; + raytracing_pipeline_create_info.libraries.pNext = NULL; + auto vkCreateRayTracingPipelinesKHR = PFN_vkCreateRayTracingPipelinesKHR(vkGetDeviceProcAddr(device, "vkCreateRayTracingPipelinesKHR")); + vkCreateRayTracingPipelinesKHR(device, VK_NULL_HANDLE, 1, &raytracing_pipeline_create_info, nullptr, &pipeline->impl.pipeline); + } + + { + VkPhysicalDeviceRayTracingPropertiesKHR ray_tracing_properties; + ray_tracing_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_KHR; + ray_tracing_properties.pNext = nullptr; + VkPhysicalDeviceProperties2 device_properties{}; + device_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; + device_properties.pNext = &ray_tracing_properties; + vkGetPhysicalDeviceProperties2(gpu, &device_properties); + + uint32_t shader_binding_table_size = ray_tracing_properties.shaderGroupHandleSize * 3; + + VkBufferCreateInfo buf_info = {}; + buf_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buf_info.pNext = NULL; + buf_info.size = shader_binding_table_size; + buf_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR; + buf_info.flags = 0; + + VkMemoryAllocateInfo mem_alloc; + memset(&mem_alloc, 0, sizeof(VkMemoryAllocateInfo)); + mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + mem_alloc.pNext = NULL; + mem_alloc.allocationSize = 0; + mem_alloc.memoryTypeIndex = 0; + + VkMemoryRequirements mem_reqs = {}; + vkCreateBuffer(device, &buf_info, NULL, &pipeline->impl.shader_binding_table); + vkGetBufferMemoryRequirements(device, pipeline->impl.shader_binding_table, &mem_reqs); + + mem_alloc.allocationSize = mem_reqs.size; + memory_type_from_properties(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &mem_alloc.memoryTypeIndex); + + VkDeviceMemory mem; + vkAllocateMemory(device, &mem_alloc, NULL, &mem); + + vkBindBufferMemory(device, pipeline->impl.shader_binding_table, mem, 0); + void* data; + vkMapMemory(device, mem, 0, shader_binding_table_size, 0, (void **)&data); + auto vkGetRayTracingShaderGroupHandlesKHR = PFN_vkGetRayTracingShaderGroupHandlesKHR(vkGetDeviceProcAddr(device, "vkGetRayTracingShaderGroupHandlesKHR")); + vkGetRayTracingShaderGroupHandlesKHR(device, pipeline->impl.pipeline, 0, 3, shader_binding_table_size, data); + vkUnmapMemory(device, mem); + } + + { + VkDescriptorPoolSize type_counts[3]; + memset(type_counts, 0, sizeof(type_counts)); + + type_counts[0].type = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; + type_counts[0].descriptorCount = 1; + + type_counts[1].type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + type_counts[1].descriptorCount = 1; + + type_counts[2].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + type_counts[2].descriptorCount = 1; + + VkDescriptorPoolCreateInfo descriptor_pool_create_info = {}; + descriptor_pool_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + descriptor_pool_create_info.pNext = NULL; + descriptor_pool_create_info.maxSets = 1024; + descriptor_pool_create_info.poolSizeCount = 3; + descriptor_pool_create_info.pPoolSizes = type_counts; + + vkCreateDescriptorPool(device, &descriptor_pool_create_info, nullptr, &descriptor_pool); + + VkDescriptorSetAllocateInfo alloc_info = {}; + alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + alloc_info.pNext = NULL; + alloc_info.descriptorPool = descriptor_pool; + alloc_info.descriptorSetCount = 1; + alloc_info.pSetLayouts = &pipeline->impl.descriptor_set_layout; + vkAllocateDescriptorSets(device, &alloc_info, &pipeline->impl.descriptor_set); + } +} + +void kinc_raytrace_pipeline_destroy(kinc_raytrace_pipeline_t *pipeline) { + vkDestroyPipeline(device, pipeline->impl.pipeline, nullptr); + vkDestroyPipelineLayout(device, pipeline->impl.pipeline_layout, nullptr); + vkDestroyDescriptorSetLayout(device, pipeline->impl.descriptor_set_layout, nullptr); +} + +uint64_t get_buffer_device_address(VkBuffer buffer) { + VkBufferDeviceAddressInfoKHR buffer_device_address_info = {}; + buffer_device_address_info.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO; + buffer_device_address_info.buffer = buffer; + auto vkGetBufferDeviceAddressKHR = PFN_vkGetBufferDeviceAddressKHR(vkGetDeviceProcAddr(device, "vkGetBufferDeviceAddressKHR")); + return vkGetBufferDeviceAddressKHR(device, &buffer_device_address_info); +} + +void kinc_raytrace_acceleration_structure_init(kinc_raytrace_acceleration_structure_t *accel, kinc_g5_command_list_t *command_list, kinc_g5_vertex_buffer_t *vb, kinc_g5_index_buffer_t *ib) { + + auto vkGetAccelerationStructureMemoryRequirementsKHR = PFN_vkGetAccelerationStructureMemoryRequirementsKHR(vkGetDeviceProcAddr(device, "vkGetAccelerationStructureMemoryRequirementsKHR")); + auto vkCreateAccelerationStructureKHR = PFN_vkCreateAccelerationStructureKHR(vkGetDeviceProcAddr(device, "vkCreateAccelerationStructureKHR")); + auto vkBindAccelerationStructureMemoryKHR = PFN_vkBindAccelerationStructureMemoryKHR(vkGetDeviceProcAddr(device, "vkBindAccelerationStructureMemoryKHR")); + auto vkGetAccelerationStructureDeviceAddressKHR = PFN_vkGetAccelerationStructureDeviceAddressKHR(vkGetDeviceProcAddr(device, "vkGetAccelerationStructureDeviceAddressKHR")); + auto vkGetBufferDeviceAddressKHR = PFN_vkGetBufferDeviceAddressKHR(vkGetDeviceProcAddr(device, "vkGetBufferDeviceAddressKHR")); + + { + VkDeviceOrHostAddressConstKHR vertex_data_device_address{}; + VkDeviceOrHostAddressConstKHR index_data_device_address{}; + + vertex_data_device_address.deviceAddress = get_buffer_device_address(vb->impl.vertices.buf); + index_data_device_address.deviceAddress = get_buffer_device_address(ib->impl.buf); + + VkAccelerationStructureCreateGeometryTypeInfoKHR acceleration_create_geometry_info{}; + acceleration_create_geometry_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR; + acceleration_create_geometry_info.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; + acceleration_create_geometry_info.maxPrimitiveCount = 1; + acceleration_create_geometry_info.indexType = VK_INDEX_TYPE_UINT32; + acceleration_create_geometry_info.maxVertexCount = vb->impl.myCount; + acceleration_create_geometry_info.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT; + acceleration_create_geometry_info.allowsTransforms = VK_FALSE; + + VkAccelerationStructureCreateInfoKHR acceleration_create_info{}; + acceleration_create_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR; + acceleration_create_info.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; + acceleration_create_info.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; + acceleration_create_info.maxGeometryCount = 1; + acceleration_create_info.pGeometryInfos = &acceleration_create_geometry_info; + vkCreateAccelerationStructureKHR(device, &acceleration_create_info, nullptr, &accel->impl.bottom_level_acceleration_structure); + + // Bind object memory to the bottom level acceleration structure + VkMemoryRequirements2 memory_requirements_2{}; + memory_requirements_2.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2; + + VkAccelerationStructureMemoryRequirementsInfoKHR acceleration_memory_requirements{}; + acceleration_memory_requirements.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR; + acceleration_memory_requirements.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR; + acceleration_memory_requirements.buildType = VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR; + acceleration_memory_requirements.accelerationStructure = accel->impl.bottom_level_acceleration_structure; + vkGetAccelerationStructureMemoryRequirementsKHR(device, &acceleration_memory_requirements, &memory_requirements_2); + + VkMemoryRequirements memory_requirements = memory_requirements_2.memoryRequirements; + + VkMemoryAllocateInfo memory_allocate_info{}; + memory_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + memory_allocate_info.allocationSize = memory_requirements.size; + memory_type_from_properties(memory_requirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &memory_allocate_info.memoryTypeIndex); + + VkDeviceMemory memory = VK_NULL_HANDLE; + vkAllocateMemory(device, &memory_allocate_info, nullptr, &memory); + + VkBindAccelerationStructureMemoryInfoKHR bind_acceleration_memory_info{}; + bind_acceleration_memory_info.sType = VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_KHR; + bind_acceleration_memory_info.accelerationStructure = accel->impl.bottom_level_acceleration_structure; + bind_acceleration_memory_info.memory = memory; + vkBindAccelerationStructureMemoryKHR(device, 1, &bind_acceleration_memory_info); + + VkAccelerationStructureGeometryKHR acceleration_geometry{}; + acceleration_geometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; + acceleration_geometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR; + acceleration_geometry.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; + acceleration_geometry.geometry.triangles.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR; + acceleration_geometry.geometry.triangles.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT; + acceleration_geometry.geometry.triangles.vertexData.deviceAddress = vertex_data_device_address.deviceAddress; + acceleration_geometry.geometry.triangles.vertexStride = vb->impl.myStride; + acceleration_geometry.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32; + acceleration_geometry.geometry.triangles.indexData.deviceAddress = index_data_device_address.deviceAddress; + + VkBuffer scratch_buffer = VK_NULL_HANDLE; + VkDeviceMemory scratch_memory = VK_NULL_HANDLE; + + acceleration_memory_requirements.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR; + acceleration_memory_requirements.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR; + acceleration_memory_requirements.buildType = VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR; + acceleration_memory_requirements.accelerationStructure = accel->impl.bottom_level_acceleration_structure; + vkGetAccelerationStructureMemoryRequirementsKHR(device, &acceleration_memory_requirements, &memory_requirements_2); + + VkBufferCreateInfo buffer_create_info{}; + buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_create_info.size = memory_requirements_2.memoryRequirements.size; + buffer_create_info.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; + buffer_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + vkCreateBuffer(device, &buffer_create_info, nullptr, &scratch_buffer); + + vkGetBufferMemoryRequirements(device, scratch_buffer, &memory_requirements); + + VkMemoryAllocateFlagsInfo memory_allocate_flags_info{}; + memory_allocate_flags_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO; + memory_allocate_flags_info.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR; + + memory_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + memory_allocate_info.pNext = &memory_allocate_flags_info; + memory_allocate_info.allocationSize = memory_requirements.size; + memory_type_from_properties(memory_requirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &memory_allocate_info.memoryTypeIndex); + vkAllocateMemory(device, &memory_allocate_info, nullptr, &scratch_memory); + vkBindBufferMemory(device, scratch_buffer, scratch_memory, 0); + + VkBufferDeviceAddressInfoKHR buffer_device_address_info{}; + buffer_device_address_info.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO; + buffer_device_address_info.buffer = scratch_buffer; + uint64_t scratch_buffer_device_address = vkGetBufferDeviceAddressKHR(device, &buffer_device_address_info); + + VkAccelerationStructureBuildGeometryInfoKHR acceleration_build_geometry_info{}; + acceleration_build_geometry_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR; + acceleration_build_geometry_info.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; + acceleration_build_geometry_info.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; + acceleration_build_geometry_info.update = VK_FALSE; + acceleration_build_geometry_info.dstAccelerationStructure = accel->impl.bottom_level_acceleration_structure; + acceleration_build_geometry_info.geometryArrayOfPointers = VK_FALSE; + acceleration_build_geometry_info.geometryCount = 1; + + VkAccelerationStructureGeometryKHR * const acceleration_geometries[1] = { &acceleration_geometry }; + acceleration_build_geometry_info.ppGeometries = &acceleration_geometries[0]; + acceleration_build_geometry_info.scratchData.deviceAddress = scratch_buffer_device_address; + + VkAccelerationStructureBuildOffsetInfoKHR acceleration_build_offset_info{}; + acceleration_build_offset_info.primitiveCount = 1; + acceleration_build_offset_info.primitiveOffset = 0x0; + acceleration_build_offset_info.firstVertex = 0; + acceleration_build_offset_info.transformOffset = 0x0; + + VkAccelerationStructureBuildOffsetInfoKHR *acceleration_build_offsets[1] = {&acceleration_build_offset_info}; + + { + VkCommandBufferAllocateInfo cmd_buf_allocate_info{}; + cmd_buf_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + cmd_buf_allocate_info.commandPool = cmd_pool; + cmd_buf_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + cmd_buf_allocate_info.commandBufferCount = 1; + + VkCommandBuffer command_buffer; + vkAllocateCommandBuffers(device, &cmd_buf_allocate_info, &command_buffer); + + VkCommandBufferBeginInfo command_buffer_info{}; + command_buffer_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + vkBeginCommandBuffer(command_buffer, &command_buffer_info); + + auto vkCmdBuildAccelerationStructureKHR = PFN_vkCmdBuildAccelerationStructureKHR(vkGetDeviceProcAddr(device, "vkCmdBuildAccelerationStructureKHR")); + vkCmdBuildAccelerationStructureKHR(command_buffer, 1, &acceleration_build_geometry_info, &acceleration_build_offsets[0]); + + vkEndCommandBuffer(command_buffer); + + VkSubmitInfo submit_info{}; + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.commandBufferCount = 1; + submit_info.pCommandBuffers = &command_buffer; + + VkFenceCreateInfo fence_info{}; + fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + fence_info.flags = 0; + + VkFence fence; + vkCreateFence(device, &fence_info, nullptr, &fence); + + VkResult result = vkQueueSubmit(queue, 1, &submit_info, fence); + vkWaitForFences(device, 1, &fence, VK_TRUE, 100000000000); + vkDestroyFence(device, fence, nullptr); + vkFreeCommandBuffers(device, cmd_pool, 1, &command_buffer); + } + + VkAccelerationStructureDeviceAddressInfoKHR acceleration_device_address_info{}; + acceleration_device_address_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR; + acceleration_device_address_info.accelerationStructure = accel->impl.bottom_level_acceleration_structure; + + accel->impl.bottom_level_acceleration_structure_handle = vkGetAccelerationStructureDeviceAddressKHR(device, &acceleration_device_address_info); + + vkFreeMemory(device, scratch_memory, nullptr); + vkDestroyBuffer(device, scratch_buffer, nullptr); + } + + { + VkAccelerationStructureCreateGeometryTypeInfoKHR acceleration_create_geometry_info{}; + acceleration_create_geometry_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_GEOMETRY_TYPE_INFO_KHR; + acceleration_create_geometry_info.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR; + acceleration_create_geometry_info.maxPrimitiveCount = 1; + acceleration_create_geometry_info.allowsTransforms = VK_FALSE; + + VkAccelerationStructureCreateInfoKHR acceleration_create_info{}; + acceleration_create_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR; + acceleration_create_info.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; + acceleration_create_info.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; + acceleration_create_info.maxGeometryCount = 1; + acceleration_create_info.pGeometryInfos = &acceleration_create_geometry_info; + vkCreateAccelerationStructureKHR(device, &acceleration_create_info, nullptr, &accel->impl.top_level_acceleration_structure); + + // Bind object memory to the top level acceleration structure + VkMemoryRequirements2 memory_requirements_2{}; + memory_requirements_2.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2; + + VkAccelerationStructureMemoryRequirementsInfoKHR acceleration_memory_requirements{}; + acceleration_memory_requirements.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR; + acceleration_memory_requirements.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_KHR; + acceleration_memory_requirements.buildType = VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR; + acceleration_memory_requirements.accelerationStructure = accel->impl.top_level_acceleration_structure; + vkGetAccelerationStructureMemoryRequirementsKHR(device, &acceleration_memory_requirements, &memory_requirements_2); + + VkMemoryRequirements memory_requirements = memory_requirements_2.memoryRequirements; + + VkMemoryAllocateInfo memory_allocate_info{}; + memory_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + memory_allocate_info.allocationSize = memory_requirements.size; + memory_type_from_properties(memory_requirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &memory_allocate_info.memoryTypeIndex); + + VkDeviceMemory memory = VK_NULL_HANDLE; + vkAllocateMemory(device, &memory_allocate_info, nullptr, &memory); + + VkBindAccelerationStructureMemoryInfoKHR bind_acceleration_memory_info{}; + bind_acceleration_memory_info.sType = VK_STRUCTURE_TYPE_BIND_ACCELERATION_STRUCTURE_MEMORY_INFO_KHR; + bind_acceleration_memory_info.accelerationStructure = accel->impl.top_level_acceleration_structure; + bind_acceleration_memory_info.memory = memory; + vkBindAccelerationStructureMemoryKHR(device, 1, &bind_acceleration_memory_info); + + VkTransformMatrixKHR transform_matrix = { + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f}; + + VkAccelerationStructureInstanceKHR instance{}; + instance.transform = transform_matrix; + instance.instanceCustomIndex = 0; + instance.mask = 0xFF; + instance.instanceShaderBindingTableRecordOffset = 0; + instance.flags = VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR; + instance.accelerationStructureReference = accel->impl.bottom_level_acceleration_structure_handle; + + VkBuffer instances_buffer; + + VkBufferCreateInfo buf_info = {}; + buf_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buf_info.pNext = NULL; + buf_info.size = sizeof(instance); + buf_info.usage = VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; + buf_info.flags = 0; + + VkMemoryAllocateInfo mem_alloc; + memset(&mem_alloc, 0, sizeof(VkMemoryAllocateInfo)); + mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + mem_alloc.pNext = NULL; + mem_alloc.allocationSize = 0; + mem_alloc.memoryTypeIndex = 0; + + VkMemoryRequirements mem_reqs = {}; + + vkCreateBuffer(device, &buf_info, NULL, &instances_buffer); + + vkGetBufferMemoryRequirements(device, instances_buffer, &mem_reqs); + + mem_alloc.allocationSize = mem_reqs.size; + memory_type_from_properties(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &mem_alloc.memoryTypeIndex); + + VkMemoryAllocateFlagsInfo memory_allocate_flags_info = {}; + memory_allocate_flags_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO; + memory_allocate_flags_info.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR; + mem_alloc.pNext = &memory_allocate_flags_info; + + VkDeviceMemory mem; + vkAllocateMemory(device, &mem_alloc, NULL, &mem); + + vkBindBufferMemory(device, instances_buffer, mem, 0); + void* data; + vkMapMemory(device, mem, 0, sizeof(VkAccelerationStructureInstanceKHR), 0, (void **)&data); + memcpy(data, &instance, sizeof(VkAccelerationStructureInstanceKHR)); + vkUnmapMemory(device, mem); + + VkDeviceOrHostAddressConstKHR instance_data_device_address{}; + instance_data_device_address.deviceAddress = get_buffer_device_address(instances_buffer); + + VkAccelerationStructureGeometryKHR acceleration_geometry{}; + acceleration_geometry.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR; + acceleration_geometry.flags = VK_GEOMETRY_OPAQUE_BIT_KHR; + acceleration_geometry.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR; + acceleration_geometry.geometry.instances.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR; + acceleration_geometry.geometry.instances.arrayOfPointers = VK_FALSE; + acceleration_geometry.geometry.instances.data.deviceAddress = instance_data_device_address.deviceAddress; + + VkAccelerationStructureGeometryKHR * const acceleration_geometries[1] = { &acceleration_geometry }; + + VkBuffer scratch_buffer = VK_NULL_HANDLE; + VkDeviceMemory scratch_memory = VK_NULL_HANDLE; + + acceleration_memory_requirements.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_INFO_KHR; + acceleration_memory_requirements.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_KHR; + acceleration_memory_requirements.buildType = VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR; + acceleration_memory_requirements.accelerationStructure = accel->impl.bottom_level_acceleration_structure; + vkGetAccelerationStructureMemoryRequirementsKHR(device, &acceleration_memory_requirements, &memory_requirements_2); + + VkBufferCreateInfo buffer_create_info{}; + buffer_create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_create_info.size = memory_requirements_2.memoryRequirements.size; + buffer_create_info.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_KHR | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; + buffer_create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + vkCreateBuffer(device, &buffer_create_info, nullptr, &scratch_buffer); + + vkGetBufferMemoryRequirements(device, scratch_buffer, &memory_requirements); + + memory_allocate_flags_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO; + memory_allocate_flags_info.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR; + + memory_allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + memory_allocate_info.pNext = &memory_allocate_flags_info; + memory_allocate_info.allocationSize = memory_requirements.size; + memory_type_from_properties(memory_requirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &memory_allocate_info.memoryTypeIndex); + vkAllocateMemory(device, &memory_allocate_info, nullptr, &scratch_memory); + vkBindBufferMemory(device, scratch_buffer, scratch_memory, 0); + + VkBufferDeviceAddressInfoKHR buffer_device_address_info{}; + buffer_device_address_info.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO; + buffer_device_address_info.buffer = scratch_buffer; + uint64_t scratch_buffer_device_address = vkGetBufferDeviceAddressKHR(device, &buffer_device_address_info); + + VkAccelerationStructureBuildGeometryInfoKHR acceleration_build_geometry_info{}; + acceleration_build_geometry_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR; + acceleration_build_geometry_info.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; + acceleration_build_geometry_info.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; + acceleration_build_geometry_info.update = VK_FALSE; + acceleration_build_geometry_info.srcAccelerationStructure = VK_NULL_HANDLE; + acceleration_build_geometry_info.dstAccelerationStructure = accel->impl.top_level_acceleration_structure; + acceleration_build_geometry_info.geometryArrayOfPointers = VK_FALSE; + acceleration_build_geometry_info.geometryCount = 1; + acceleration_build_geometry_info.ppGeometries = &acceleration_geometries[0]; + acceleration_build_geometry_info.scratchData.deviceAddress = scratch_buffer_device_address; + + VkAccelerationStructureBuildOffsetInfoKHR acceleration_build_offset_info{}; + acceleration_build_offset_info.primitiveCount = 1; + acceleration_build_offset_info.primitiveOffset = 0x0; + acceleration_build_offset_info.firstVertex = 0; + acceleration_build_offset_info.transformOffset = 0x0; + + VkAccelerationStructureBuildOffsetInfoKHR *acceleration_build_offsets[1] = {&acceleration_build_offset_info}; + + { + VkCommandBufferAllocateInfo cmd_buf_allocate_info{}; + cmd_buf_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + cmd_buf_allocate_info.commandPool = cmd_pool; + cmd_buf_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + cmd_buf_allocate_info.commandBufferCount = 1; + + VkCommandBuffer command_buffer; + vkAllocateCommandBuffers(device, &cmd_buf_allocate_info, &command_buffer); + + VkCommandBufferBeginInfo command_buffer_info{}; + command_buffer_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + vkBeginCommandBuffer(command_buffer, &command_buffer_info); + + auto vkCmdBuildAccelerationStructureKHR = PFN_vkCmdBuildAccelerationStructureKHR(vkGetDeviceProcAddr(device, "vkCmdBuildAccelerationStructureKHR")); + vkCmdBuildAccelerationStructureKHR(command_buffer, 1, &acceleration_build_geometry_info, &acceleration_build_offsets[0]); + + vkEndCommandBuffer(command_buffer); + + VkSubmitInfo submit_info{}; + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.commandBufferCount = 1; + submit_info.pCommandBuffers = &command_buffer; + + VkFenceCreateInfo fence_info{}; + fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + fence_info.flags = 0; + + VkFence fence; + vkCreateFence(device, &fence_info, nullptr, &fence); + + VkResult result = vkQueueSubmit(queue, 1, &submit_info, fence); + vkWaitForFences(device, 1, &fence, VK_TRUE, 100000000000); + vkDestroyFence(device, fence, nullptr); + + vkFreeCommandBuffers(device, cmd_pool, 1, &command_buffer); + } + + VkAccelerationStructureDeviceAddressInfoKHR acceleration_device_address_info{}; + acceleration_device_address_info.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_DEVICE_ADDRESS_INFO_KHR; + acceleration_device_address_info.accelerationStructure = accel->impl.top_level_acceleration_structure; + + accel->impl.top_level_acceleration_structure_handle = vkGetAccelerationStructureDeviceAddressKHR(device, &acceleration_device_address_info); + + vkFreeMemory(device, scratch_memory, nullptr); + vkDestroyBuffer(device, scratch_buffer, nullptr); + } +} + +void kinc_raytrace_acceleration_structure_destroy(kinc_raytrace_acceleration_structure_t *accel) { + auto vkDestroyAccelerationStructureKHR = PFN_vkDestroyAccelerationStructureKHR(vkGetDeviceProcAddr(device, "vkDestroyAccelerationStructureKHR")); + vkDestroyAccelerationStructureKHR(device, accel->impl.bottom_level_acceleration_structure, nullptr); + vkDestroyAccelerationStructureKHR(device, accel->impl.top_level_acceleration_structure, nullptr); +} + +void kinc_raytrace_set_acceleration_structure(kinc_raytrace_acceleration_structure_t *_accel) { + accel = _accel; +} + +void kinc_raytrace_set_pipeline(kinc_raytrace_pipeline_t *_pipeline) { + pipeline = _pipeline; +} + +void kinc_raytrace_set_target(kinc_g5_texture_t *_output) { + output = _output; +} + +void kinc_raytrace_dispatch_rays(kinc_g5_command_list_t *command_list) { + VkWriteDescriptorSetAccelerationStructureKHR descriptor_acceleration_structure_info{}; + descriptor_acceleration_structure_info.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR; + descriptor_acceleration_structure_info.accelerationStructureCount = 1; + descriptor_acceleration_structure_info.pAccelerationStructures = &accel->impl.top_level_acceleration_structure; + + VkWriteDescriptorSet acceleration_structure_write{}; + acceleration_structure_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + acceleration_structure_write.pNext = &descriptor_acceleration_structure_info; + acceleration_structure_write.dstSet = pipeline->impl.descriptor_set; + acceleration_structure_write.dstBinding = 0; + acceleration_structure_write.descriptorCount = 1; + acceleration_structure_write.descriptorType = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; + + VkDescriptorImageInfo image_descriptor{}; + image_descriptor.imageView = output->impl.texture.view; + image_descriptor.imageLayout = VK_IMAGE_LAYOUT_GENERAL; + + VkDescriptorBufferInfo buffer_descriptor{}; + buffer_descriptor.buffer = pipeline->_constant_buffer->impl.buf; + buffer_descriptor.range = VK_WHOLE_SIZE; + buffer_descriptor.offset = 0; + + VkWriteDescriptorSet result_image_write{}; + result_image_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + result_image_write.pNext = nullptr; + result_image_write.dstSet = pipeline->impl.descriptor_set; + result_image_write.dstBinding = 1; + result_image_write.descriptorCount = 1; + result_image_write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + result_image_write.pImageInfo = &image_descriptor; + + VkWriteDescriptorSet uniform_buffer_write{}; + uniform_buffer_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + uniform_buffer_write.pNext = nullptr; + uniform_buffer_write.dstSet = pipeline->impl.descriptor_set; + uniform_buffer_write.dstBinding = 2; + uniform_buffer_write.descriptorCount = 1; + uniform_buffer_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + uniform_buffer_write.pBufferInfo = &buffer_descriptor; + + VkWriteDescriptorSet write_descriptor_sets[3] = { acceleration_structure_write, result_image_write, uniform_buffer_write }; + vkUpdateDescriptorSets(device, 3, write_descriptor_sets, 0, VK_NULL_HANDLE); + + VkPhysicalDeviceRayTracingPropertiesKHR ray_tracing_properties; + ray_tracing_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_KHR; + ray_tracing_properties.pNext = nullptr; + VkPhysicalDeviceProperties2 device_properties{}; + device_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; + device_properties.pNext = &ray_tracing_properties; + vkGetPhysicalDeviceProperties2(gpu, &device_properties); + + // Setup the strided buffer regions pointing to the shaders in our shader binding table + VkStridedBufferRegionKHR raygen_shader_sbt_entry{}; + raygen_shader_sbt_entry.buffer = pipeline->impl.shader_binding_table; + raygen_shader_sbt_entry.offset = (VkDeviceSize)(ray_tracing_properties.shaderGroupHandleSize * INDEX_RAYGEN); + raygen_shader_sbt_entry.size = ray_tracing_properties.shaderGroupHandleSize; + + VkStridedBufferRegionKHR miss_shader_sbt_entry{}; + miss_shader_sbt_entry.buffer = pipeline->impl.shader_binding_table; + miss_shader_sbt_entry.offset = (VkDeviceSize)(ray_tracing_properties.shaderGroupHandleSize * INDEX_MISS); + miss_shader_sbt_entry.size = ray_tracing_properties.shaderGroupHandleSize; + + VkStridedBufferRegionKHR hit_shader_sbt_entry{}; + hit_shader_sbt_entry.buffer = pipeline->impl.shader_binding_table; + hit_shader_sbt_entry.offset = (VkDeviceSize)(ray_tracing_properties.shaderGroupHandleSize * INDEX_CLOSEST_HIT); + hit_shader_sbt_entry.size = ray_tracing_properties.shaderGroupHandleSize; + + VkStridedBufferRegionKHR callable_shader_sbt_entry{}; + + vkCmdEndRenderPass(command_list->impl._buffer); + + // Dispatch the ray tracing commands + vkCmdBindPipeline(command_list->impl._buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline->impl.pipeline); + vkCmdBindDescriptorSets(command_list->impl._buffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline->impl.pipeline_layout, 0, 1, &pipeline->impl.descriptor_set, 0, 0); + + auto vkCmdTraceRaysKHR = PFN_vkCmdTraceRaysKHR(vkGetDeviceProcAddr(device, "vkCmdTraceRaysKHR")); + vkCmdTraceRaysKHR(command_list->impl._buffer, &raygen_shader_sbt_entry, &miss_shader_sbt_entry, &hit_shader_sbt_entry, &callable_shader_sbt_entry, output->texWidth, output->texHeight, 1); + + vkCmdBeginRenderPass(command_list->impl._buffer, ¤tRenderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); +} + +void kinc_raytrace_copy(kinc_g5_command_list_t *command_list, kinc_g5_render_target_t* target, kinc_g5_texture_t *source) { + + vkCmdEndRenderPass(command_list->impl._buffer); + + VkImageCopy copy_region{}; + copy_region.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; + copy_region.srcOffset = {0, 0, 0}; + copy_region.dstSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; + copy_region.dstOffset = {0, 0, 0}; + copy_region.extent = {(uint32_t)output->texWidth, (uint32_t)output->texHeight, 1}; + + if (target->contextId < 0) { + vkCmdCopyImage(command_list->impl._buffer, output->impl.texture.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + Kore::Vulkan::buffers[current_buffer].image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©_region); + } + else { + vkCmdCopyImage(command_list->impl._buffer, output->impl.texture.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + target->impl.sourceImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©_region); + } + + vkCmdBeginRenderPass(command_list->impl._buffer, ¤tRenderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); +} + +#endif // KORE_VKRT diff --git a/Backends/Graphics5/Vulkan/Sources/Kore/RayTraceImpl.h b/Backends/Graphics5/Vulkan/Sources/Kore/RayTraceImpl.h new file mode 100644 index 000000000..36269853a --- /dev/null +++ b/Backends/Graphics5/Vulkan/Sources/Kore/RayTraceImpl.h @@ -0,0 +1,30 @@ +#pragma once + +#ifdef KORE_VKRT + +#include "MiniVulkan.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + VkPipeline pipeline; + VkPipelineLayout pipeline_layout; + VkDescriptorSet descriptor_set; + VkDescriptorSetLayout descriptor_set_layout; + VkBuffer shader_binding_table; +} kinc_raytrace_pipeline_impl_t; + +typedef struct { + VkAccelerationStructureKHR top_level_acceleration_structure; + VkAccelerationStructureKHR bottom_level_acceleration_structure; + uint64_t top_level_acceleration_structure_handle; + uint64_t bottom_level_acceleration_structure_handle; +} kinc_raytrace_acceleration_structure_impl_t; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Backends/Graphics5/Vulkan/Sources/Kore/RenderTarget5Impl.cpp b/Backends/Graphics5/Vulkan/Sources/Kore/RenderTarget5Impl.cpp index 6cd5930c0..f3ba88f0b 100644 --- a/Backends/Graphics5/Vulkan/Sources/Kore/RenderTarget5Impl.cpp +++ b/Backends/Graphics5/Vulkan/Sources/Kore/RenderTarget5Impl.cpp @@ -9,15 +9,41 @@ #include #include +#include extern VkDevice device; -extern VkRenderPass render_pass; +extern VkRenderPass framebuffer_render_pass; +extern VkRenderPass rendertarget_render_pass; extern uint32_t swapchainImageCount; extern VkPhysicalDevice gpu; -extern kinc_g5_texture_t *vulkanTextures[8]; -extern kinc_g5_render_target_t *vulkanRenderTargets[8]; +extern kinc_g5_texture_t *vulkanTextures[16]; +extern kinc_g5_render_target_t *vulkanRenderTargets[16]; bool memory_type_from_properties(uint32_t typeBits, VkFlags requirements_mask, uint32_t* typeIndex); +void setup_init_cmd(); +void flush_init_cmd(); + +extern VkCommandPool cmd_pool; +extern VkQueue queue; +extern VkCommandBuffer setup_cmd; + +static VkFormat convert_format(kinc_g5_render_target_format_t format) { + switch (format) { + case KINC_G5_RENDER_TARGET_FORMAT_128BIT_FLOAT: + return VK_FORMAT_R32G32B32A32_SFLOAT; + case KINC_G5_RENDER_TARGET_FORMAT_64BIT_FLOAT: + return VK_FORMAT_R16G16B16A16_SFLOAT; + case KINC_G5_RENDER_TARGET_FORMAT_32BIT_RED_FLOAT: + return VK_FORMAT_R32_SFLOAT; + case KINC_G5_RENDER_TARGET_FORMAT_16BIT_RED_FLOAT: + return VK_FORMAT_R16_SFLOAT; + case KINC_G5_RENDER_TARGET_FORMAT_8BIT_RED: + return VK_FORMAT_R8_UNORM; + case KINC_G5_RENDER_TARGET_FORMAT_32BIT: + default: + return VK_FORMAT_B8G8R8A8_UNORM; + } +} void setImageLayout(VkCommandBuffer _buffer, VkImage image, VkImageAspectFlags aspectMask, VkImageLayout oldImageLayout, VkImageLayout newImageLayout) { VkImageMemoryBarrier imageMemoryBarrier = {}; @@ -33,12 +59,21 @@ void setImageLayout(VkCommandBuffer _buffer, VkImage image, VkImageAspectFlags a imageMemoryBarrier.subresourceRange.levelCount = 1; imageMemoryBarrier.subresourceRange.layerCount = 1; - // if (oldImageLayout == VK_IMAGE_LAYOUT_UNDEFINED) imageMemoryBarrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT; - if (oldImageLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) imageMemoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - if (oldImageLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) imageMemoryBarrier.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - if (oldImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - if (oldImageLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) imageMemoryBarrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; - if (newImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + if (oldImageLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) { + imageMemoryBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + } + if (oldImageLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { + imageMemoryBarrier.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + } + if (oldImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) { + imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + } + if (oldImageLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { + imageMemoryBarrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; + } + if (newImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { + imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + } if (newImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL) { if (oldImageLayout != VK_IMAGE_LAYOUT_UNDEFINED) imageMemoryBarrier.srcAccessMask = imageMemoryBarrier.srcAccessMask | VK_ACCESS_TRANSFER_READ_BIT; imageMemoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; @@ -47,144 +82,32 @@ void setImageLayout(VkCommandBuffer _buffer, VkImage image, VkImageAspectFlags a imageMemoryBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; if (oldImageLayout != VK_IMAGE_LAYOUT_UNDEFINED) imageMemoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; } - if (newImageLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) + if (newImageLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { imageMemoryBarrier.dstAccessMask = imageMemoryBarrier.dstAccessMask | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + } if (newImageLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { if (oldImageLayout != VK_IMAGE_LAYOUT_UNDEFINED) imageMemoryBarrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT; imageMemoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; } - VkPipelineStageFlags srcStageFlags = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - VkPipelineStageFlags destStageFlags = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + VkPipelineStageFlags srcStageFlags = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; + VkPipelineStageFlags dstStageFlags = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; - vkCmdPipelineBarrier(_buffer, srcStageFlags, destStageFlags, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier); + vkCmdPipelineBarrier(_buffer, srcStageFlags, dstStageFlags, 0, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier); } void kinc_g5_render_target_init(kinc_g5_render_target_t *target, int width, int height, int depthBufferBits, bool antialiasing, - kinc_g5_render_target_format_t format, int stencilBufferBits, int contextId) { + kinc_g5_render_target_format_t format, int stencilBufferBits, int contextId) { target->width = width; target->height = height; target->contextId = contextId; target->texWidth = width; target->texHeight = height; - /**{ - VkFormatProperties formatProperties; - VkResult err; - - vkGetPhysicalDeviceFormatProperties(gpu, VK_FORMAT_R8G8B8A8_UNORM, &formatProperties); - assert(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_DST_BIT); - - VkImageCreateInfo imageCreateInfo = {}; - imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - imageCreateInfo.pNext = NULL; - imageCreateInfo.imageType = VK_IMAGE_TYPE_2D; - imageCreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM; - imageCreateInfo.extent = {(uint32_t)width, (uint32_t)height, 1}; - imageCreateInfo.mipLevels = 1; - imageCreateInfo.arrayLayers = 1; - imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT; - imageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - imageCreateInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - imageCreateInfo.flags = 0; - imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; - - err = vkCreateImage(device, &imageCreateInfo, nullptr, &destImage); - assert(!err); - - VkMemoryRequirements memoryRequirements; - vkGetImageMemoryRequirements(device, destImage, &memoryRequirements); - - VkMemoryAllocateInfo allocationInfo = {}; - allocationInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - allocationInfo.pNext = nullptr; - allocationInfo.memoryTypeIndex = 0; - - vkGetImageMemoryRequirements(device, destImage, &memoryRequirements); - allocationInfo.allocationSize = memoryRequirements.size; - bool pass = memory_type_from_properties(memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &allocationInfo.memoryTypeIndex); - assert(pass); - err = vkAllocateMemory(device, &allocationInfo, nullptr, &destMemory); - assert(!err); - err = vkBindImageMemory(device, destImage, destMemory, 0); - assert(!err); - - setImageLayout(destImage, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - VkImageViewCreateInfo view = {}; - view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - view.pNext = nullptr; - view.image = VK_NULL_HANDLE; - view.viewType = VK_IMAGE_VIEW_TYPE_2D; - view.format = VK_FORMAT_R8G8B8A8_UNORM; - view.components = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A}; - view.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; - view.image = destImage; - err = vkCreateImageView(device, &view, nullptr, &destView); - assert(!err); - } - - { - VkFormatProperties formatProperties; - VkResult err; - - vkGetPhysicalDeviceFormatProperties(gpu, VK_FORMAT_R8G8B8A8_UNORM, &formatProperties); - assert(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_SRC_BIT); - - VkImageCreateInfo image = {}; - image.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image.pNext = nullptr; - image.imageType = VK_IMAGE_TYPE_2D; - image.format = VK_FORMAT_R8G8B8A8_UNORM; - image.extent.width = width; - image.extent.height = height; - image.extent.depth = 1; - image.mipLevels = 1; - image.arrayLayers = 1; - image.samples = VK_SAMPLE_COUNT_1_BIT; - image.tiling = VK_IMAGE_TILING_OPTIMAL; - image.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - image.flags = 0; - - VkImageViewCreateInfo colorImageView = {}; - colorImageView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - colorImageView.pNext = nullptr; - colorImageView.viewType = VK_IMAGE_VIEW_TYPE_2D; - colorImageView.format = VK_FORMAT_R8G8B8A8_UNORM; - colorImageView.flags = 0; - colorImageView.subresourceRange = {}; - colorImageView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - colorImageView.subresourceRange.baseMipLevel = 0; - colorImageView.subresourceRange.levelCount = 1; - colorImageView.subresourceRange.baseArrayLayer = 0; - colorImageView.subresourceRange.layerCount = 1; - - err = vkCreateImage(device, &image, nullptr, &sourceImage); - assert(!err); - - VkMemoryRequirements memoryRequirements; - vkGetImageMemoryRequirements(device, sourceImage, &memoryRequirements); - - VkMemoryAllocateInfo allocationInfo = {}; - allocationInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - allocationInfo.pNext = nullptr; - allocationInfo.memoryTypeIndex = 0; - - vkGetImageMemoryRequirements(device, sourceImage, &memoryRequirements); - allocationInfo.allocationSize = memoryRequirements.size; - bool pass = memory_type_from_properties(memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &allocationInfo.memoryTypeIndex); - assert(pass); - - err = vkAllocateMemory(device, &allocationInfo, nullptr, &sourceMemory); - assert(!err); - - err = vkBindImageMemory(device, sourceImage, sourceMemory, 0); - assert(!err); - setImageLayout(sourceImage, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - - colorImageView.image = sourceImage; - err = vkCreateImageView(device, &colorImageView, nullptr, &sourceView); - assert(!err); - }*/ + target->impl.format = convert_format(format); + target->impl.depthBufferBits = depthBufferBits; + target->impl.stage = 0; + target->impl.stage_depth = -1; + target->impl.readbackBufferCreated = false; VkSamplerCreateInfo samplerInfo = {}; samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; @@ -204,130 +127,293 @@ void kinc_g5_render_target_init(kinc_g5_render_target_t *target, int width, int samplerInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; samplerInfo.unnormalizedCoordinates = VK_FALSE; - VkResult err = vkCreateSampler(device, &samplerInfo, nullptr, &target->impl.sampler); - assert(!err); - - /*VkImageCreateInfo imageInfo = {}; - imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - imageInfo.pNext = nullptr; - imageInfo.imageType = VK_IMAGE_TYPE_2D; - imageInfo.format = VK_FORMAT_B8G8R8A8_UNORM; - imageInfo.extent = { (uint32_t)width, (uint32_t)height, 1 }; - imageInfo.mipLevels = 1; - imageInfo.arrayLayers = 1; - imageInfo.samples = VK_SAMPLE_COUNT_1_BIT; - imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - imageInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - imageInfo.flags = 0; - - err = vkCreateImage(device, &imageInfo, NULL, &image); - assert(!err); - - VkMemoryRequirements memoryRequirements; - vkGetImageMemoryRequirements(device, image, &memoryRequirements); - - VkMemoryAllocateInfo allocationInfo = {}; - allocationInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - allocationInfo.pNext = nullptr; - allocationInfo.allocationSize = memoryRequirements.size; - allocationInfo.memoryTypeIndex = 0; - - bool pass = memory_type_from_properties(memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &allocationInfo.memoryTypeIndex); - assert(pass); - - err = vkAllocateMemory(device, &allocationInfo, NULL, &memory); + VkResult err = vkCreateSampler(device, &samplerInfo, nullptr, &target->impl.bilinear_sampler); assert(!err); - err = vkBindImageMemory(device, image, memory, 0); + samplerInfo.magFilter = VK_FILTER_NEAREST; + samplerInfo.minFilter = VK_FILTER_NEAREST; + err = vkCreateSampler(device, &samplerInfo, NULL, &target->impl.point_sampler); assert(!err); - VkImageViewCreateInfo viewInfo = {}; - viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - viewInfo.pNext = nullptr; - viewInfo.image = image; - viewInfo.format = VK_FORMAT_B8G8R8A8_UNORM; // is that OK? - viewInfo.components.r = VK_COMPONENT_SWIZZLE_R; - viewInfo.components.g = VK_COMPONENT_SWIZZLE_G; - viewInfo.components.b = VK_COMPONENT_SWIZZLE_B; - viewInfo.components.a = VK_COMPONENT_SWIZZLE_A; - viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - viewInfo.subresourceRange.baseMipLevel = 0; - viewInfo.subresourceRange.levelCount = 1; - viewInfo.subresourceRange.baseArrayLayer = 0; - viewInfo.subresourceRange.layerCount = 1; - viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; - viewInfo.flags = 0; - - err = vkCreateImageView(device, &viewInfo, nullptr, &view); - assert(!err);*/ - - /*VkAttachmentReference colorReference = {}; - colorReference.attachment = 0; - colorReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - VkSubpassDescription subpass = {}; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.flags = 0; - subpass.inputAttachmentCount = 0; - subpass.pInputAttachments = nullptr; - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = &colorReference; - subpass.pResolveAttachments = nullptr; - subpass.pDepthStencilAttachment = nullptr; - subpass.preserveAttachmentCount = 0; - subpass.pPreserveAttachments = nullptr; - - VkAttachmentDescription attachment; - attachment.format = VK_FORMAT_B8G8R8A8_UNORM; - attachment.samples = VK_SAMPLE_COUNT_1_BIT; - attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachment.initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - attachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - VkRenderPassCreateInfo renderPassInfo = {}; - renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - renderPassInfo.pNext = nullptr; - renderPassInfo.attachmentCount = 1; - renderPassInfo.pAttachments = &attachment; - renderPassInfo.subpassCount = 1; - renderPassInfo.pSubpasses = &subpass; - renderPassInfo.dependencyCount = 0; - renderPassInfo.pDependencies = nullptr; - - err = vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass); - assert(!err); - - VkFramebufferCreateInfo fbufCreateInfo = {}; - fbufCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - fbufCreateInfo.pNext = nullptr; - fbufCreateInfo.renderPass = renderPass; - fbufCreateInfo.attachmentCount = 1; - fbufCreateInfo.pAttachments = &sourceView; - fbufCreateInfo.width = width; - fbufCreateInfo.height = height; - fbufCreateInfo.layers = 1; - - err = vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &framebuffer); - assert(!err); - - createDescriptorSet(nullptr, this, desc_set);*/ + if (contextId >= 0) { + { + VkFormatProperties formatProperties; + VkResult err; + + vkGetPhysicalDeviceFormatProperties(gpu, target->impl.format, &formatProperties); + assert(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_BLIT_SRC_BIT); + + VkImageCreateInfo image = {}; + image.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + image.pNext = nullptr; + image.imageType = VK_IMAGE_TYPE_2D; + image.format = target->impl.format; + image.extent.width = width; + image.extent.height = height; + image.extent.depth = 1; + image.mipLevels = 1; + image.arrayLayers = 1; + image.samples = VK_SAMPLE_COUNT_1_BIT; + image.tiling = VK_IMAGE_TILING_OPTIMAL; + image.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; + image.flags = 0; + + VkImageViewCreateInfo colorImageView = {}; + colorImageView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + colorImageView.pNext = nullptr; + colorImageView.viewType = VK_IMAGE_VIEW_TYPE_2D; + colorImageView.format = target->impl.format; + colorImageView.flags = 0; + colorImageView.subresourceRange = {}; + colorImageView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + colorImageView.subresourceRange.baseMipLevel = 0; + colorImageView.subresourceRange.levelCount = 1; + colorImageView.subresourceRange.baseArrayLayer = 0; + colorImageView.subresourceRange.layerCount = 1; + + err = vkCreateImage(device, &image, nullptr, &target->impl.sourceImage); + assert(!err); + + VkMemoryRequirements memoryRequirements; + vkGetImageMemoryRequirements(device, target->impl.sourceImage, &memoryRequirements); + + VkMemoryAllocateInfo allocationInfo = {}; + allocationInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + allocationInfo.pNext = nullptr; + allocationInfo.memoryTypeIndex = 0; + allocationInfo.allocationSize = memoryRequirements.size; + bool pass = memory_type_from_properties(memoryRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &allocationInfo.memoryTypeIndex); + assert(pass); + + err = vkAllocateMemory(device, &allocationInfo, nullptr, &target->impl.sourceMemory); + assert(!err); + + err = vkBindImageMemory(device, target->impl.sourceImage, target->impl.sourceMemory, 0); + assert(!err); + + setup_init_cmd(); + setImageLayout(setup_cmd, target->impl.sourceImage, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + flush_init_cmd(); + + colorImageView.image = target->impl.sourceImage; + err = vkCreateImageView(device, &colorImageView, nullptr, &target->impl.sourceView); + assert(!err); + } + + if (depthBufferBits > 0) { + const VkFormat depth_format = VK_FORMAT_D16_UNORM; + VkImageCreateInfo image = {}; + image.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + image.pNext = NULL; + image.imageType = VK_IMAGE_TYPE_2D; + image.format = depth_format; + image.extent.width = width; + image.extent.height = height; + image.extent.depth = 1; + image.mipLevels = 1; + image.arrayLayers = 1; + image.samples = VK_SAMPLE_COUNT_1_BIT; + image.tiling = VK_IMAGE_TILING_OPTIMAL; + image.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + image.flags = 0; + + /* create image */ + err = vkCreateImage(device, &image, NULL, &target->impl.depthImage); + assert(!err); + + VkMemoryAllocateInfo mem_alloc = {}; + mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + mem_alloc.pNext = NULL; + mem_alloc.allocationSize = 0; + mem_alloc.memoryTypeIndex = 0; + + VkImageViewCreateInfo view = {}; + view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + view.pNext = NULL; + view.image = target->impl.depthImage; + view.format = depth_format; + view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + view.subresourceRange.baseMipLevel = 0; + view.subresourceRange.levelCount = 1; + view.subresourceRange.baseArrayLayer = 0; + view.subresourceRange.layerCount = 1; + view.flags = 0; + view.viewType = VK_IMAGE_VIEW_TYPE_2D; + + VkMemoryRequirements mem_reqs = {}; + bool pass; + + /* get memory requirements for this object */ + vkGetImageMemoryRequirements(device, target->impl.depthImage, &mem_reqs); + + /* select memory size and type */ + mem_alloc.allocationSize = mem_reqs.size; + pass = memory_type_from_properties(mem_reqs.memoryTypeBits, 0, /* No requirements */ &mem_alloc.memoryTypeIndex); + assert(pass); + + /* allocate memory */ + err = vkAllocateMemory(device, &mem_alloc, NULL, &target->impl.depthMemory); + assert(!err); + + /* bind memory */ + err = vkBindImageMemory(device, target->impl.depthImage, target->impl.depthMemory, 0); + assert(!err); + + setup_init_cmd(); + setImageLayout(setup_cmd, target->impl.depthImage, VK_IMAGE_ASPECT_DEPTH_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + flush_init_cmd(); + + /* create image view */ + err = vkCreateImageView(device, &view, NULL, &target->impl.depthView); + assert(!err); + } + + VkImageView attachments[2]; + attachments[0] = target->impl.sourceView; + + if (depthBufferBits > 0) { + attachments[1] = target->impl.depthView; + } + + VkFramebufferCreateInfo fbufCreateInfo = {}; + fbufCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + fbufCreateInfo.pNext = nullptr; + fbufCreateInfo.renderPass = contextId >= 0 ? rendertarget_render_pass : framebuffer_render_pass; + fbufCreateInfo.attachmentCount = depthBufferBits > 0 ? 2 : 1; + fbufCreateInfo.pAttachments = attachments; + fbufCreateInfo.width = width; + fbufCreateInfo.height = height; + fbufCreateInfo.layers = 1; + + err = vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &target->impl.framebuffer); + assert(!err); + } } void kinc_g5_render_target_init_cube(kinc_g5_render_target_t *target, int cubeMapSize, int depthBufferBits, bool antialiasing, - kinc_g5_render_target_format_t format, int stencilBufferBits, int contextId) {} + kinc_g5_render_target_format_t format, int stencilBufferBits, int contextId) {} void kinc_g5_render_target_destroy(kinc_g5_render_target_t *target) {} - + void kinc_g5_render_target_use_color_as_texture(kinc_g5_render_target_t *target, kinc_g5_texture_unit_t unit) { + target->impl.stage = unit.impl.binding - 2; vulkanRenderTargets[unit.impl.binding - 2] = target; vulkanTextures[unit.impl.binding - 2] = nullptr; - //** if (Program5Impl::current != nullptr) - //** vkCmdBindDescriptorSets(draw_cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, Program5Impl::current->pipeline_layout, 0, 1, &desc_set, 0, nullptr); } - void kinc_g5_render_target_use_depth_as_texture(kinc_g5_render_target_t *target, kinc_g5_texture_unit_t unit) {} +void kinc_g5_render_target_use_depth_as_texture(kinc_g5_render_target_t *target, kinc_g5_texture_unit_t unit) { + target->impl.stage_depth = unit.impl.binding - 2; + vulkanRenderTargets[unit.impl.binding - 2] = target; + vulkanTextures[unit.impl.binding - 2] = nullptr; +} -void kinc_g5_render_target_set_depth_stencil_from(kinc_g5_render_target_t *target, kinc_g5_render_target_t *source) {} +void kinc_g5_render_target_set_depth_stencil_from(kinc_g5_render_target_t *target, kinc_g5_render_target_t *source) { + target->impl.depthImage = source->impl.depthImage; + target->impl.depthMemory = source->impl.depthMemory; + target->impl.depthView = source->impl.depthView; + target->impl.depthBufferBits = source->impl.depthBufferBits; + + // vkDestroyFramebuffer(device, target->impl.framebuffer, nullptr); + // vkDestroyRenderPass(device, target->impl.renderPass, nullptr); + + { + VkAttachmentDescription attachments[2]; + attachments[0].format = target->impl.format; + attachments[0].samples = VK_SAMPLE_COUNT_1_BIT; + attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; + attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attachments[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + attachments[0].flags = 0; + + if (target->impl.depthBufferBits > 0) { + attachments[1].format = VK_FORMAT_D16_UNORM; + attachments[1].samples = VK_SAMPLE_COUNT_1_BIT; + attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE; + attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attachments[1].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + attachments[1].flags = 0; + } + + VkAttachmentReference color_reference = {}; + color_reference.attachment = 0; + color_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + VkAttachmentReference depth_reference = {}; + depth_reference.attachment = 1; + depth_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + VkSubpassDescription subpass = {}; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.flags = 0; + subpass.inputAttachmentCount = 0; + subpass.pInputAttachments = nullptr; + subpass.colorAttachmentCount = 1; + subpass.pColorAttachments = &color_reference; + subpass.pResolveAttachments = nullptr; + subpass.pDepthStencilAttachment = target->impl.depthBufferBits > 0 ? &depth_reference : nullptr; + subpass.preserveAttachmentCount = 0; + subpass.pPreserveAttachments = nullptr; + + VkSubpassDependency dependencies[2]; + memset(&dependencies, 0, sizeof(dependencies)); + + // TODO: depth-stencil-something + dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; + dependencies[0].dstSubpass = 0; + dependencies[0].srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependencies[0].srcAccessMask = VK_ACCESS_SHADER_READ_BIT; + dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + + dependencies[1].srcSubpass = 0; + dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; + dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependencies[1].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dependencies[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + + VkRenderPassCreateInfo rp_info = {}; + rp_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + rp_info.pNext = nullptr; + rp_info.attachmentCount = target->impl.depthBufferBits > 0 ? 2 : 1; + rp_info.pAttachments = attachments; + rp_info.subpassCount = 1; + rp_info.pSubpasses = &subpass; + rp_info.dependencyCount = 2; + rp_info.pDependencies = dependencies; + + // TODO + // VkResult err = vkCreateRenderPass(device, &rp_info, NULL, &target->impl.renderPass); + // assert(!err); + } + + { + VkImageView attachments[2]; + attachments[0] = target->impl.sourceView; + + if (target->impl.depthBufferBits > 0) { + attachments[1] = target->impl.depthView; + } + + VkFramebufferCreateInfo fbufCreateInfo = {}; + fbufCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + fbufCreateInfo.pNext = nullptr; + fbufCreateInfo.renderPass = VK_NULL_HANDLE; // target->impl.renderPass; // TODO + fbufCreateInfo.attachmentCount = target->impl.depthBufferBits > 0 ? 2 : 1; + fbufCreateInfo.pAttachments = attachments; + fbufCreateInfo.width = target->width; + fbufCreateInfo.height = target->height; + fbufCreateInfo.layers = 1; + + VkResult err = vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &target->impl.framebuffer); + assert(!err); + } +} diff --git a/Backends/Graphics5/Vulkan/Sources/Kore/RenderTarget5Impl.h b/Backends/Graphics5/Vulkan/Sources/Kore/RenderTarget5Impl.h index 990b464df..cacc15609 100644 --- a/Backends/Graphics5/Vulkan/Sources/Kore/RenderTarget5Impl.h +++ b/Backends/Graphics5/Vulkan/Sources/Kore/RenderTarget5Impl.h @@ -1,30 +1,27 @@ #pragma once -#include - -#ifdef min -#undef min -#endif - -#ifdef max -#undef max -#endif - -#ifdef RegisterClass -#undef RegisterClass -#endif +#include "MiniVulkan.h" typedef struct { - VkImage destImage; - VkDeviceMemory destMemory; - VkImageView destView; - VkImage sourceImage; VkDeviceMemory sourceMemory; VkImageView sourceView; + VkImage depthImage; + VkDeviceMemory depthMemory; + VkImageView depthView; + int depthBufferBits; + VkFramebuffer framebuffer; - VkDescriptorSet desc_set; - VkSampler sampler; - VkRenderPass renderPass; + VkSampler bilinear_sampler; + VkSampler point_sampler; + + VkFormat format; + + VkBuffer readbackBuffer; + VkDeviceMemory readbackMemory; + bool readbackBufferCreated; + + int stage; + int stage_depth; } RenderTarget5Impl; diff --git a/Backends/Graphics5/Vulkan/Sources/Kore/Texture5Impl.cpp b/Backends/Graphics5/Vulkan/Sources/Kore/Texture5Impl.cpp index c5d8b1ac8..f4898d4cc 100644 --- a/Backends/Graphics5/Vulkan/Sources/Kore/Texture5Impl.cpp +++ b/Backends/Graphics5/Vulkan/Sources/Kore/Texture5Impl.cpp @@ -13,119 +13,23 @@ extern VkDevice device; extern VkPhysicalDevice gpu; -VkCommandBuffer setup_cmd; +extern VkCommandBuffer setup_cmd; extern VkCommandPool cmd_pool; extern VkQueue queue; -extern bool use_staging_buffer; +bool use_staging_buffer = false; bool memory_type_from_properties(uint32_t typeBits, VkFlags requirements_mask, uint32_t* typeIndex); +void set_image_layout(VkImage image, VkImageAspectFlags aspectMask, VkImageLayout old_image_layout, VkImageLayout new_image_layout); +void flush_init_cmd(); -namespace { - void demo_flush_init_cmd() { - VkResult err; - - if (setup_cmd == VK_NULL_HANDLE) return; - - err = vkEndCommandBuffer(setup_cmd); - assert(!err); - - const VkCommandBuffer cmd_bufs[] = {setup_cmd}; - VkFence nullFence = {VK_NULL_HANDLE}; - VkSubmitInfo submit_info = {}; - submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submit_info.pNext = NULL; - submit_info.waitSemaphoreCount = 0; - submit_info.pWaitSemaphores = NULL; - submit_info.pWaitDstStageMask = NULL; - submit_info.commandBufferCount = 1; - submit_info.pCommandBuffers = cmd_bufs; - submit_info.signalSemaphoreCount = 0; - submit_info.pSignalSemaphores = NULL; - - err = vkQueueSubmit(queue, 1, &submit_info, nullFence); - assert(!err); - - err = vkQueueWaitIdle(queue); - assert(!err); - - vkFreeCommandBuffers(device, cmd_pool, 1, cmd_bufs); - setup_cmd = VK_NULL_HANDLE; - } - - void demo_set_image_layout(VkImage image, VkImageAspectFlags aspectMask, VkImageLayout old_image_layout, VkImageLayout new_image_layout) { - VkResult err; - - if (setup_cmd == VK_NULL_HANDLE) { - VkCommandBufferAllocateInfo cmd = {}; - cmd.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - cmd.pNext = NULL; - cmd.commandPool = cmd_pool; - cmd.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - cmd.commandBufferCount = 1; - - err = vkAllocateCommandBuffers(device, &cmd, &setup_cmd); - assert(!err); - - VkCommandBufferInheritanceInfo cmd_buf_hinfo = {}; - cmd_buf_hinfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO; - cmd_buf_hinfo.pNext = NULL; - cmd_buf_hinfo.renderPass = VK_NULL_HANDLE; - cmd_buf_hinfo.subpass = 0; - cmd_buf_hinfo.framebuffer = VK_NULL_HANDLE; - cmd_buf_hinfo.occlusionQueryEnable = VK_FALSE; - cmd_buf_hinfo.queryFlags = 0; - cmd_buf_hinfo.pipelineStatistics = 0; - - VkCommandBufferBeginInfo cmd_buf_info = {}; - cmd_buf_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - cmd_buf_info.pNext = NULL; - cmd_buf_info.flags = 0; - cmd_buf_info.pInheritanceInfo = &cmd_buf_hinfo; - - err = vkBeginCommandBuffer(setup_cmd, &cmd_buf_info); - assert(!err); - } - - VkImageMemoryBarrier image_memory_barrier = {}; - image_memory_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; - image_memory_barrier.pNext = NULL; - image_memory_barrier.srcAccessMask = 0; - image_memory_barrier.dstAccessMask = 0; - image_memory_barrier.oldLayout = old_image_layout; - image_memory_barrier.newLayout = new_image_layout; - image_memory_barrier.image = image; - image_memory_barrier.subresourceRange = {aspectMask, 0, 1, 0, 1}; - - if (new_image_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) { - /* Make sure anything that was copying from this image has completed */ - image_memory_barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; - } - - if (new_image_layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) { - image_memory_barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - } - - if (new_image_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) { - image_memory_barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - } - - if (new_image_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) { - // Make sure any Copy or CPU writes to image are flushed - image_memory_barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; - } - - VkImageMemoryBarrier* pmemory_barrier = &image_memory_barrier; - - VkPipelineStageFlags src_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - VkPipelineStageFlags dest_stages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; - - vkCmdPipelineBarrier(setup_cmd, src_stages, dest_stages, 0, 0, NULL, 0, NULL, 1, pmemory_barrier); - } - - void demo_prepare_texture_image(uint8_t *tex_colors, uint32_t tex_width, uint32_t tex_height, texture_object* tex_obj, VkImageTiling tiling, - VkImageUsageFlags usage, VkFlags required_props, VkDeviceSize& deviceSize) { - const VkFormat tex_format = VK_FORMAT_B8G8R8A8_UNORM; +#ifdef KORE_ANDROID +struct kinc_g4_texture_t; +extern "C" void kinc_g4_texture_init_from_id(kinc_g4_texture_t *, unsigned) {} +#endif +namespace { + void prepare_texture_image(uint8_t *tex_colors, uint32_t tex_width, uint32_t tex_height, texture_object* tex_obj, VkImageTiling tiling, + VkImageUsageFlags usage, VkFlags required_props, VkDeviceSize& deviceSize, VkFormat tex_format) { VkResult err; bool pass; @@ -171,7 +75,7 @@ namespace { err = vkBindImageMemory(device, tex_obj->image, tex_obj->mem, 0); assert(!err); - if (required_props & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) { + if (required_props & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT && tex_colors != nullptr) { VkImageSubresource subres = {}; subres.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; subres.mipLevel = 0; @@ -185,37 +89,139 @@ namespace { err = vkMapMemory(device, tex_obj->mem, 0, mem_alloc.allocationSize, 0, (void**)&data); assert(!err); - for (uint32_t y = 0; y < tex_height; y++) { - // uint32_t *row = (uint32_t *)((char *)data + layout.rowPitch * y); - for (uint32_t x = 0; x < tex_width; x++) { - data[y * layout.rowPitch + x * 4 + 0] = tex_colors[y * tex_width * 4 + x * 4 + 2]; - data[y * layout.rowPitch + x * 4 + 1] = tex_colors[y * tex_width * 4 + x * 4 + 1]; - data[y * layout.rowPitch + x * 4 + 2] = tex_colors[y * tex_width * 4 + x * 4 + 0]; - data[y * layout.rowPitch + x * 4 + 3] = tex_colors[y * tex_width * 4 + x * 4 + 3]; - // row[x] = tex_colors[(x & 1) ^ (y & 1)]; + if (tex_format == VK_FORMAT_R8_UNORM) { + for (uint32_t y = 0; y < tex_height; y++) { + for (uint32_t x = 0; x < tex_width; x++) { + data[y * layout.rowPitch + x] = tex_colors[y * tex_width + x]; + } + } + } + else if (tex_format == VK_FORMAT_R32_SFLOAT) { + uint32_t *data32 = (uint32_t *)data; + uint32_t *tex_colors32 = (uint32_t *)tex_colors; + for (uint32_t y = 0; y < tex_height; y++) { + for (uint32_t x = 0; x < tex_width; x++) { + data32[y * (layout.rowPitch / 4) + x] = tex_colors32[y * tex_width + x]; + } + } + } + else if (tex_format == VK_FORMAT_R16_SFLOAT) { + uint16_t *data16 = (uint16_t *)data; + uint16_t *tex_colors16 = (uint16_t *)tex_colors; + for (uint32_t y = 0; y < tex_height; y++) { + for (uint32_t x = 0; x < tex_width; x++) { + data16[y * (layout.rowPitch / 4) + x] = tex_colors16[y * tex_width + x]; + } + } + } + else if (tex_format == VK_FORMAT_R32G32B32A32_SFLOAT) { + uint32_t *data32 = (uint32_t *)data; + uint32_t *tex_colors32 = (uint32_t *)tex_colors; + for (uint32_t y = 0; y < tex_height; y++) { + for (uint32_t x = 0; x < tex_width; x++) { + data32[y * (layout.rowPitch / 4) + x * 4 + 0] = tex_colors32[y * tex_width * 4 + x * 4 + 0]; + data32[y * (layout.rowPitch / 4) + x * 4 + 1] = tex_colors32[y * tex_width * 4 + x * 4 + 1]; + data32[y * (layout.rowPitch / 4) + x * 4 + 2] = tex_colors32[y * tex_width * 4 + x * 4 + 2]; + data32[y * (layout.rowPitch / 4) + x * 4 + 3] = tex_colors32[y * tex_width * 4 + x * 4 + 3]; + } + } + } + else if (tex_format == VK_FORMAT_R16G16B16A16_SFLOAT) { + uint16_t *data16 = (uint16_t *)data; + uint16_t *tex_colors16 = (uint16_t *)tex_colors; + for (uint32_t y = 0; y < tex_height; y++) { + for (uint32_t x = 0; x < tex_width; x++) { + data16[y * (layout.rowPitch / 4) + x * 4 + 0] = tex_colors16[y * tex_width * 4 + x * 4 + 0]; + data16[y * (layout.rowPitch / 4) + x * 4 + 1] = tex_colors16[y * tex_width * 4 + x * 4 + 1]; + data16[y * (layout.rowPitch / 4) + x * 4 + 2] = tex_colors16[y * tex_width * 4 + x * 4 + 2]; + data16[y * (layout.rowPitch / 4) + x * 4 + 3] = tex_colors16[y * tex_width * 4 + x * 4 + 3]; + } + } + } + else { + for (uint32_t y = 0; y < tex_height; y++) { + // uint32_t *row = (uint32_t *)((char *)data + layout.rowPitch * y); + for (uint32_t x = 0; x < tex_width; x++) { + data[y * layout.rowPitch + x * 4 + 0] = tex_colors[y * tex_width * 4 + x * 4 + 2]; + data[y * layout.rowPitch + x * 4 + 1] = tex_colors[y * tex_width * 4 + x * 4 + 1]; + data[y * layout.rowPitch + x * 4 + 2] = tex_colors[y * tex_width * 4 + x * 4 + 0]; + data[y * layout.rowPitch + x * 4 + 3] = tex_colors[y * tex_width * 4 + x * 4 + 3]; + // row[x] = tex_colors[(x & 1) ^ (y & 1)]; + } } } vkUnmapMemory(device, tex_obj->mem); } - tex_obj->imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - demo_set_image_layout(tex_obj->image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, tex_obj->imageLayout); + if (usage & VK_IMAGE_USAGE_STORAGE_BIT) { + tex_obj->imageLayout = VK_IMAGE_LAYOUT_GENERAL; + } + else { + tex_obj->imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + } + set_image_layout(tex_obj->image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, tex_obj->imageLayout); // setting the image layout does not reference the actual memory so no need to add a mem ref } - void demo_destroy_texture_image(texture_object* tex_obj) { + void destroy_texture_image(texture_object* tex_obj) { // clean up staging resources vkDestroyImage(device, tex_obj->image, NULL); vkFreeMemory(device, tex_obj->mem, NULL); } } +static VkFormat convert_format(kinc_image_format_t format) { + switch (format) { + case KINC_IMAGE_FORMAT_RGBA128: + return VK_FORMAT_R32G32B32A32_SFLOAT; + case KINC_IMAGE_FORMAT_RGBA64: + return VK_FORMAT_R16G16B16A16_SFLOAT; + case KINC_IMAGE_FORMAT_RGB24: + return VK_FORMAT_B8G8R8A8_UNORM; + case KINC_IMAGE_FORMAT_A32: + return VK_FORMAT_R32_SFLOAT; + case KINC_IMAGE_FORMAT_A16: + return VK_FORMAT_R16_SFLOAT; + case KINC_IMAGE_FORMAT_GREY8: + return VK_FORMAT_R8_UNORM; + case KINC_IMAGE_FORMAT_BGRA32: + return VK_FORMAT_B8G8R8A8_UNORM; + case KINC_IMAGE_FORMAT_RGBA32: + return VK_FORMAT_B8G8R8A8_UNORM; + default: + return VK_FORMAT_B8G8R8A8_UNORM; + } +} + +static int format_byte_size(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: + return 4; + } +} + void kinc_g5_texture_init_from_image(kinc_g5_texture_t *texture, kinc_image_t *image) { texture->texWidth = image->width; texture->texHeight = image->height; + texture->impl.stride = format_byte_size(image->format) * texture->texWidth; - const VkFormat tex_format = VK_FORMAT_B8G8R8A8_UNORM; + const VkFormat tex_format = convert_format(image->format); VkFormatProperties props; VkResult err; @@ -223,21 +229,23 @@ void kinc_g5_texture_init_from_image(kinc_g5_texture_t *texture, kinc_image_t *i if ((props.linearTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) && !use_staging_buffer) { // Device can texture using linear textures - demo_prepare_texture_image((uint8_t*)image->data, (uint32_t)image->width, (uint32_t)image->height, &texture->impl.texture, VK_IMAGE_TILING_LINEAR, VK_IMAGE_USAGE_SAMPLED_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, texture->impl.deviceSize); + prepare_texture_image((uint8_t*)image->data, (uint32_t)image->width, (uint32_t)image->height, &texture->impl.texture, VK_IMAGE_TILING_LINEAR, VK_IMAGE_USAGE_SAMPLED_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, texture->impl.deviceSize, tex_format); + + flush_init_cmd(); } else if (props.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) { // Must use staging buffer to copy linear texture to optimized texture_object staging_texture; memset(&staging_texture, 0, sizeof(staging_texture)); - demo_prepare_texture_image((uint8_t*)image->data, (uint32_t)image->width, (uint32_t)image->height, &staging_texture, VK_IMAGE_TILING_LINEAR, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, texture->impl.deviceSize); - demo_prepare_texture_image((uint8_t*)image->data, (uint32_t)image->width, (uint32_t)image->height, &texture->impl.texture, VK_IMAGE_TILING_OPTIMAL, + prepare_texture_image((uint8_t*)image->data, (uint32_t)image->width, (uint32_t)image->height, &staging_texture, VK_IMAGE_TILING_LINEAR, VK_IMAGE_USAGE_TRANSFER_SRC_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, texture->impl.deviceSize, tex_format); + prepare_texture_image((uint8_t*)image->data, (uint32_t)image->width, (uint32_t)image->height, &texture->impl.texture, VK_IMAGE_TILING_OPTIMAL, (VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT), VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - texture->impl.deviceSize); - demo_set_image_layout(staging_texture.image, VK_IMAGE_ASPECT_COLOR_BIT, staging_texture.imageLayout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - demo_set_image_layout(texture->impl.texture.image, VK_IMAGE_ASPECT_COLOR_BIT, texture->impl.texture.imageLayout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + texture->impl.deviceSize, tex_format); + set_image_layout(staging_texture.image, VK_IMAGE_ASPECT_COLOR_BIT, staging_texture.imageLayout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + set_image_layout(texture->impl.texture.image, VK_IMAGE_ASPECT_COLOR_BIT, texture->impl.texture.imageLayout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); VkImageCopy copy_region = {}; copy_region.srcSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1}; @@ -250,14 +258,13 @@ void kinc_g5_texture_init_from_image(kinc_g5_texture_t *texture, kinc_image_t *i VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©_region); - demo_set_image_layout(texture->impl.texture.image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, texture->impl.texture.imageLayout); + set_image_layout(texture->impl.texture.image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, texture->impl.texture.imageLayout); - demo_flush_init_cmd(); + flush_init_cmd(); - demo_destroy_texture_image(&staging_texture); + destroy_texture_image(&staging_texture); } else { - // Can't support VK_FORMAT_B8G8R8A8_UNORM !? assert(!"No support for B8G8R8A8_UNORM as texture image format"); } @@ -290,19 +297,78 @@ void kinc_g5_texture_init_from_image(kinc_g5_texture_t *texture, kinc_image_t *i view.flags = 0; // create sampler - err = vkCreateSampler(device, &sampler, NULL, &texture->impl.texture.sampler); + err = vkCreateSampler(device, &sampler, NULL, &texture->impl.texture.bilinear_sampler); + assert(!err); + + sampler.magFilter = VK_FILTER_NEAREST; + sampler.minFilter = VK_FILTER_NEAREST; + err = vkCreateSampler(device, &sampler, NULL, &texture->impl.texture.point_sampler); assert(!err); // create image view view.image = texture->impl.texture.image; err = vkCreateImageView(device, &view, NULL, &texture->impl.texture.view); assert(!err); - - Kore::Vulkan::createDescriptorSet(nullptr, texture, nullptr, texture->impl.desc_set); // TODO } void kinc_g5_texture_init(kinc_g5_texture_t* texture, int width, int height, kinc_image_format_t format) { + texture->texWidth = width; + texture->texHeight = height; + texture->impl.stride = format_byte_size(format) * texture->texWidth; + + const VkFormat tex_format = convert_format(format); + VkFormatProperties props; + VkResult err; + + vkGetPhysicalDeviceFormatProperties(gpu, tex_format, &props); + + // Device can texture using linear textures + prepare_texture_image(nullptr, (uint32_t)width, (uint32_t)height, &texture->impl.texture, VK_IMAGE_TILING_LINEAR, VK_IMAGE_USAGE_SAMPLED_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, texture->impl.deviceSize, tex_format); + + flush_init_cmd(); + + VkSamplerCreateInfo sampler = {}; + sampler.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + sampler.pNext = NULL; + sampler.magFilter = VK_FILTER_LINEAR; + sampler.minFilter = VK_FILTER_LINEAR; + sampler.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; + sampler.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; + sampler.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; + sampler.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; + sampler.mipLodBias = 0.0f; + sampler.anisotropyEnable = VK_FALSE; + sampler.maxAnisotropy = 1; + sampler.compareOp = VK_COMPARE_OP_NEVER; + sampler.minLod = 0.0f; + sampler.maxLod = 0.0f; + sampler.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; + sampler.unnormalizedCoordinates = VK_FALSE; + + VkImageViewCreateInfo view = {}; + view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + view.pNext = NULL; + view.image = VK_NULL_HANDLE; + view.viewType = VK_IMAGE_VIEW_TYPE_2D; + view.format = tex_format; + view.components = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A}; + view.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; + view.flags = 0; + // create sampler + err = vkCreateSampler(device, &sampler, NULL, &texture->impl.texture.bilinear_sampler); + assert(!err); + + sampler.magFilter = VK_FILTER_NEAREST; + sampler.minFilter = VK_FILTER_NEAREST; + err = vkCreateSampler(device, &sampler, NULL, &texture->impl.texture.point_sampler); + assert(!err); + + // create image view + view.image = texture->impl.texture.image; + err = vkCreateImageView(device, &view, NULL, &texture->impl.texture.view); + assert(!err); } void kinc_g5_texture_init3d(kinc_g5_texture_t* texture, int width, int height, int depth, kinc_image_format_t format) { @@ -310,7 +376,63 @@ void kinc_g5_texture_init3d(kinc_g5_texture_t* texture, int width, int height, i } void kinc_g5_texture_init_non_sampled_access(kinc_g5_texture_t *texture, int width, int height, kinc_image_format_t format) { + texture->texWidth = width; + texture->texHeight = height; + texture->impl.stride = format_byte_size(format) * texture->texWidth; + + const VkFormat tex_format = convert_format(format); + VkFormatProperties props; + VkResult err; + + vkGetPhysicalDeviceFormatProperties(gpu, tex_format, &props); + + // Device can texture using linear textures + prepare_texture_image(nullptr, (uint32_t)width, (uint32_t)height, &texture->impl.texture, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_STORAGE_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, texture->impl.deviceSize, tex_format); + + flush_init_cmd(); + + VkSamplerCreateInfo sampler = {}; + sampler.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + sampler.pNext = NULL; + sampler.magFilter = VK_FILTER_LINEAR; + sampler.minFilter = VK_FILTER_LINEAR; + sampler.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; + sampler.addressModeU = VK_SAMPLER_ADDRESS_MODE_REPEAT; + sampler.addressModeV = VK_SAMPLER_ADDRESS_MODE_REPEAT; + sampler.addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT; + sampler.mipLodBias = 0.0f; + sampler.anisotropyEnable = VK_FALSE; + sampler.maxAnisotropy = 1; + sampler.compareOp = VK_COMPARE_OP_NEVER; + sampler.minLod = 0.0f; + sampler.maxLod = 0.0f; + sampler.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE; + sampler.unnormalizedCoordinates = VK_FALSE; + + VkImageViewCreateInfo view = {}; + view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + view.pNext = NULL; + view.image = VK_NULL_HANDLE; + view.viewType = VK_IMAGE_VIEW_TYPE_2D; + view.format = tex_format; + view.components = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A}; + view.subresourceRange = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}; + view.flags = 0; + + // create sampler + err = vkCreateSampler(device, &sampler, NULL, &texture->impl.texture.bilinear_sampler); + assert(!err); + sampler.magFilter = VK_FILTER_NEAREST; + sampler.minFilter = VK_FILTER_NEAREST; + err = vkCreateSampler(device, &sampler, NULL, &texture->impl.texture.point_sampler); + assert(!err); + + // create image view + view.image = texture->impl.texture.image; + err = vkCreateImageView(device, &view, NULL, &texture->impl.texture.view); + assert(!err); } void kinc_g5_texture_destroy(kinc_g5_texture_t *texture) {} @@ -318,7 +440,7 @@ void kinc_g5_texture_destroy(kinc_g5_texture_t *texture) {} void kinc_g5_internal_texture_set(kinc_g5_texture_t *texture, int unit) {} int kinc_g5_texture_stride(kinc_g5_texture_t *texture) { - return texture->texWidth * 4; + return texture->impl.stride; } uint8_t *kinc_g5_texture_lock(kinc_g5_texture_t *texture) { @@ -334,8 +456,8 @@ uint8_t *kinc_g5_texture_lock(kinc_g5_texture_t *texture) { VkResult err = vkMapMemory(device, texture->impl.texture.mem, 0, texture->impl.deviceSize, 0, &data); assert(!err); - //**return (u8*)data; - return NULL; + + return (uint8_t*)data; } void kinc_g5_texture_unlock(kinc_g5_texture_t *texture) { diff --git a/Backends/Graphics5/Vulkan/Sources/Kore/Texture5Impl.h b/Backends/Graphics5/Vulkan/Sources/Kore/Texture5Impl.h index abef7fc29..1a6c5236a 100644 --- a/Backends/Graphics5/Vulkan/Sources/Kore/Texture5Impl.h +++ b/Backends/Graphics5/Vulkan/Sources/Kore/Texture5Impl.h @@ -1,21 +1,10 @@ #pragma once -#include - -#ifdef min -#undef min -#endif - -#ifdef max -#undef max -#endif - -#ifdef RegisterClass -#undef RegisterClass -#endif +#include "MiniVulkan.h" struct texture_object { - VkSampler sampler; + VkSampler point_sampler; + VkSampler bilinear_sampler; VkImage image; VkImageLayout imageLayout; @@ -35,7 +24,6 @@ typedef struct { struct texture_object texture; VkDeviceSize deviceSize; - VkDescriptorSet desc_set; - uint8_t *conversionBuffer; + int stride; } Texture5Impl; diff --git a/Backends/Graphics5/Vulkan/Sources/Kore/VertexBuffer5Impl.cpp b/Backends/Graphics5/Vulkan/Sources/Kore/VertexBuffer5Impl.cpp index d8431f634..5698a6ede 100644 --- a/Backends/Graphics5/Vulkan/Sources/Kore/VertexBuffer5Impl.cpp +++ b/Backends/Graphics5/Vulkan/Sources/Kore/VertexBuffer5Impl.cpp @@ -44,6 +44,12 @@ void kinc_g5_vertex_buffer_init(kinc_g5_vertex_buffer_t *buffer, int vertexCount case KINC_G4_VERTEX_DATA_FLOAT4X4: buffer->impl.myStride += 4 * 4 * 4; break; + case KINC_G4_VERTEX_DATA_SHORT2_NORM: + buffer->impl.myStride += 2 * 2; + break; + case KINC_G4_VERTEX_DATA_SHORT4_NORM: + buffer->impl.myStride += 4 * 2; + break; } } buffer->impl.structure = *structure; @@ -53,6 +59,9 @@ void kinc_g5_vertex_buffer_init(kinc_g5_vertex_buffer_t *buffer, int vertexCount buf_info.pNext = NULL; buf_info.size = vertexCount * buffer->impl.myStride; buf_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; +#ifdef KORE_VKRT + buf_info.usage |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; +#endif buf_info.flags = 0; memset(&buffer->impl.mem_alloc, 0, sizeof(VkMemoryAllocateInfo)); @@ -77,13 +86,18 @@ void kinc_g5_vertex_buffer_init(kinc_g5_vertex_buffer_t *buffer, int vertexCount pass = memory_type_from_properties(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &buffer->impl.mem_alloc.memoryTypeIndex); assert(pass); +#ifdef KORE_VKRT + VkMemoryAllocateFlagsInfo memory_allocate_flags_info = {}; + memory_allocate_flags_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO; + memory_allocate_flags_info.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR; + buffer->impl.mem_alloc.pNext = &memory_allocate_flags_info; +#endif + err = vkAllocateMemory(device, &buffer->impl.mem_alloc, NULL, &buffer->impl.vertices.mem); assert(!err); err = vkBindBufferMemory(device, buffer->impl.vertices.buf, buffer->impl.vertices.mem, 0); assert(!err); - - // createVertexInfo(structure, vertices.info); } static void unset(kinc_g5_vertex_buffer_t *buffer) { @@ -120,10 +134,6 @@ static int setVertexAttributes(int offset) { int kinc_g5_internal_vertex_buffer_set(kinc_g5_vertex_buffer_t *buffer, int offset) { int offsetoffset = setVertexAttributes(offset); - //if (currentIndexBuffer != NULL) { - // IndexBuffer::current->_set(); - //} - return offsetoffset; } diff --git a/Backends/Graphics5/Vulkan/Sources/Kore/VertexBuffer5Impl.h b/Backends/Graphics5/Vulkan/Sources/Kore/VertexBuffer5Impl.h index 1f9907bae..db35a0837 100644 --- a/Backends/Graphics5/Vulkan/Sources/Kore/VertexBuffer5Impl.h +++ b/Backends/Graphics5/Vulkan/Sources/Kore/VertexBuffer5Impl.h @@ -2,19 +2,7 @@ #include -#include - -#ifdef min -#undef min -#endif - -#ifdef max -#undef max -#endif - -#ifdef RegisterClass -#undef RegisterClass -#endif +#include "MiniVulkan.h" struct Vertices { VkBuffer buf; @@ -22,15 +10,12 @@ struct Vertices { }; typedef struct { -//void unset(); - float* data; + float *data; int myCount; int myStride; unsigned bufferId; kinc_g5_vertex_structure_t structure; VkMemoryAllocateInfo mem_alloc; int instanceDataStepRate; - //int setVertexAttributes(int offset); struct Vertices vertices; - //static Graphics5::VertexBuffer* current; } VertexBuffer5Impl; diff --git a/Backends/Graphics5/Vulkan/Sources/Kore/Vulkan.cpp b/Backends/Graphics5/Vulkan/Sources/Kore/Vulkan.cpp index b36af2899..800877a76 100644 --- a/Backends/Graphics5/Vulkan/Sources/Kore/Vulkan.cpp +++ b/Backends/Graphics5/Vulkan/Sources/Kore/Vulkan.cpp @@ -10,6 +10,8 @@ #include #include +#include + #ifdef KORE_WINDOWS #include #endif @@ -36,6 +38,17 @@ } while (0) #endif +#ifdef VK_USE_PLATFORM_WIN32_KHR +#define KINC_SURFACE_EXT_NAME VK_KHR_WIN32_SURFACE_EXTENSION_NAME +#endif +#ifdef VK_USE_PLATFORM_XLIB_KHR +#define KINC_SURFACE_EXT_NAME VK_KHR_XLIB_SURFACE_EXTENSION_NAME +#endif +#ifdef VK_USE_PLATFORM_ANDROID_KHR +#define KINC_SURFACE_EXT_NAME VK_KHR_ANDROID_SURFACE_EXTENSION_NAME +#endif +extern "C" VkResult kinc_vulkan_create_surface(VkInstance instance,int window_index,VkSurfaceKHR *surface); + #define GET_INSTANCE_PROC_ADDR(inst, entrypoint) \ { \ fp##entrypoint = (PFN_vk##entrypoint)vkGetInstanceProcAddr(inst, "vk" #entrypoint); \ @@ -57,22 +70,20 @@ int newRenderTargetHeight; VkDevice device; VkFormat format; -VkFormat depth_format; -VkRenderPass render_pass; -// VkCommandBuffer draw_cmd; -VkDescriptorSet desc_set; VkPhysicalDevice gpu; +VkRenderPass framebuffer_render_pass; +VkRenderPass rendertarget_render_pass; VkCommandPool cmd_pool; VkQueue queue; -bool use_staging_buffer; -VkDescriptorPool desc_pool; uint32_t swapchainImageCount; VkFramebuffer *framebuffers; PFN_vkQueuePresentKHR fpQueuePresentKHR; PFN_vkAcquireNextImageKHR fpAcquireNextImageKHR; VkSemaphore presentCompleteSemaphore; +void createDescriptorLayout(); +void set_image_layout(VkImage image, VkImageAspectFlags aspectMask, VkImageLayout old_image_layout, VkImageLayout new_image_layout); -#ifndef NDEBUG +#ifdef _DEBUG #define VALIDATE #endif @@ -80,16 +91,18 @@ Kore::Vulkan::SwapchainBuffers *Kore::Vulkan::buffers; Kore::Vulkan::DepthBuffer Kore::Vulkan::depth; VkSwapchainKHR swapchain; uint32_t current_buffer; +int depthBits; +int stencilBits; +bool vsynced; -kinc_g5_texture_t *vulkanTextures[8] = {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}; -kinc_g5_render_target_t *vulkanRenderTargets[8] = {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}; +void flush_init_cmd(); -#ifdef KORE_LINUX -extern xcb_connection_t *connection; -extern xcb_screen_t *screen; -extern xcb_window_t window; -extern xcb_intern_atom_reply_t *atom_wm_delete_window; -#endif +static bool has_surface = false; + +kinc_g5_texture_t *vulkanTextures[16] = {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}; +kinc_g5_render_target_t *vulkanRenderTargets[16] = {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}; namespace { bool began = false; @@ -102,9 +115,9 @@ namespace { #endif VkSurfaceKHR surface; bool prepared; - +#ifndef KORE_ANDROID VkAllocationCallbacks allocator; - +#endif VkInstance inst; VkPhysicalDeviceProperties gpu_props; VkQueueFamilyProperties *queue_props; @@ -119,7 +132,6 @@ namespace { char *device_validation_layers[64]; #endif - int width, height; VkColorSpaceKHR color_space; PFN_vkGetPhysicalDeviceSurfaceSupportKHR fpGetPhysicalDeviceSurfaceSupportKHR; @@ -139,7 +151,7 @@ namespace { bool quit; uint32_t queue_count; - VkBool32 demo_check_layers(uint32_t check_count, char **check_names, uint32_t layer_count, VkLayerProperties *layers) { + VkBool32 check_layers(uint32_t check_count, char **check_names, uint32_t layer_count, VkLayerProperties *layers) { for (uint32_t i = 0; i < check_count; ++i) { VkBool32 found = 0; for (uint32_t j = 0; j < layer_count; ++j) { @@ -166,7 +178,7 @@ namespace { } return false; } - +#ifndef KORE_ANDROID VKAPI_ATTR void *VKAPI_CALL myrealloc(void *pUserData, void *pOriginal, size_t size, size_t alignment, VkSystemAllocationScope allocationScope) { #ifdef _MSC_VER return _aligned_realloc(pOriginal, size, alignment); @@ -179,7 +191,9 @@ namespace { #ifdef _MSC_VER return _aligned_malloc(size, alignment); #else - return aligned_alloc(alignment, size); + void *ptr; + posix_memalign(&ptr, alignment, size); + return ptr; #endif } @@ -190,7 +204,7 @@ namespace { free(pMemory); #endif } - +#endif int pow(int pow) { int ret = 1; for (int i = 0; i < pow; ++i) ret *= 2; @@ -223,25 +237,412 @@ void kinc_g5_destroy(int window) {} void kinc_internal_g5_resize(int window, int width, int height) {} -extern "C" void kinc_internal_resize(int window, int width, int height) {} +extern "C" void kinc_internal_resize(int window, int width, int height) { + if (width == 0 || height == 0) return; + newRenderTargetWidth = width; + newRenderTargetHeight = height; +} extern "C" void kinc_internal_change_framebuffer(int window, struct kinc_framebuffer_options *frame) {} +void create_swapchain() { + VkSwapchainKHR oldSwapchain = swapchain; + + // Check the surface capabilities and formats + VkSurfaceCapabilitiesKHR surfCapabilities = {}; + VkResult err = fpGetPhysicalDeviceSurfaceCapabilitiesKHR(gpu, surface, &surfCapabilities); + assert(!err); + + uint32_t presentModeCount; + err = fpGetPhysicalDeviceSurfacePresentModesKHR(gpu, surface, &presentModeCount, NULL); + assert(!err); + VkPresentModeKHR *presentModes = (VkPresentModeKHR *)malloc(presentModeCount * sizeof(VkPresentModeKHR)); + assert(presentModes); + err = fpGetPhysicalDeviceSurfacePresentModesKHR(gpu, surface, &presentModeCount, presentModes); + assert(!err); + + VkExtent2D swapchainExtent; + // width and height are either both -1, or both not -1. + if (surfCapabilities.currentExtent.width == (uint32_t)-1) { + // If the surface size is undefined, the size is set to + // the size of the images requested. + swapchainExtent.width = renderTargetWidth; + swapchainExtent.height = renderTargetHeight; + } + else { + // If the surface size is defined, the swap chain size must match + swapchainExtent = surfCapabilities.currentExtent; + renderTargetWidth = surfCapabilities.currentExtent.width; + renderTargetHeight = surfCapabilities.currentExtent.height; + } + + VkPresentModeKHR swapchainPresentMode = vsynced ? VK_PRESENT_MODE_FIFO_KHR : VK_PRESENT_MODE_MAILBOX_KHR; + + // Determine the number of VkImage's to use in the swap chain (we desire to + // own only 1 image at a time, besides the images being displayed and + // queued for display): + uint32_t desiredNumberOfSwapchainImages = surfCapabilities.minImageCount + 1; + if ((surfCapabilities.maxImageCount > 0) && (desiredNumberOfSwapchainImages > surfCapabilities.maxImageCount)) { + // Application must settle for fewer images than desired: + desiredNumberOfSwapchainImages = surfCapabilities.maxImageCount; + } + + VkSurfaceTransformFlagBitsKHR preTransform = {}; + if (surfCapabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) { + preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; + } + else { + preTransform = surfCapabilities.currentTransform; + } + + VkSwapchainCreateInfoKHR swapchain_info = {}; + swapchain_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; + swapchain_info.pNext = NULL; + swapchain_info.surface = surface; + swapchain_info.minImageCount = desiredNumberOfSwapchainImages; + swapchain_info.imageFormat = format; + swapchain_info.imageColorSpace = color_space; + swapchain_info.imageExtent.width = swapchainExtent.width; + swapchain_info.imageExtent.height = swapchainExtent.height; + swapchain_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + swapchain_info.preTransform = preTransform; + swapchain_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + swapchain_info.imageArrayLayers = 1; + swapchain_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + swapchain_info.queueFamilyIndexCount = 0; + swapchain_info.pQueueFamilyIndices = NULL; + swapchain_info.presentMode = swapchainPresentMode; + swapchain_info.oldSwapchain = oldSwapchain; + swapchain_info.clipped = true; + + uint32_t i; + + err = fpCreateSwapchainKHR(device, &swapchain_info, NULL, &swapchain); + assert(!err); + + // If we just re-created an existing swapchain, we should destroy the old + // swapchain at this point. + // Note: destroying the swapchain also cleans up all its associated + // presentable images once the platform is done with them. + if (oldSwapchain != VK_NULL_HANDLE) { + fpDestroySwapchainKHR(device, oldSwapchain, NULL); + } + + err = fpGetSwapchainImagesKHR(device, swapchain, &swapchainImageCount, NULL); + assert(!err); + + VkImage *swapchainImages = (VkImage *)malloc(swapchainImageCount * sizeof(VkImage)); + assert(swapchainImages); + err = fpGetSwapchainImagesKHR(device, swapchain, &swapchainImageCount, swapchainImages); + assert(!err); + + Kore::Vulkan::buffers = (Kore::Vulkan::SwapchainBuffers *)malloc(sizeof(Kore::Vulkan::SwapchainBuffers) * swapchainImageCount); + assert(Kore::Vulkan::buffers); + + for (i = 0; i < swapchainImageCount; i++) { + VkImageViewCreateInfo color_attachment_view = {}; + color_attachment_view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + color_attachment_view.pNext = NULL; + color_attachment_view.format = format; + color_attachment_view.components.r = VK_COMPONENT_SWIZZLE_R; + color_attachment_view.components.g = VK_COMPONENT_SWIZZLE_G; + color_attachment_view.components.b = VK_COMPONENT_SWIZZLE_B; + color_attachment_view.components.a = VK_COMPONENT_SWIZZLE_A; + color_attachment_view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + color_attachment_view.subresourceRange.baseMipLevel = 0; + color_attachment_view.subresourceRange.levelCount = 1; + color_attachment_view.subresourceRange.baseArrayLayer = 0; + color_attachment_view.subresourceRange.layerCount = 1; + color_attachment_view.viewType = VK_IMAGE_VIEW_TYPE_2D; + color_attachment_view.flags = 0; + + Kore::Vulkan::buffers[i].image = swapchainImages[i]; + + // Render loop will expect image to have been used before and in + // VK_IMAGE_LAYOUT_PRESENT_SRC_KHR + // layout and will change to COLOR_ATTACHMENT_OPTIMAL, so init the image + // to that state + set_image_layout(Kore::Vulkan::buffers[i].image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); + + color_attachment_view.image = Kore::Vulkan::buffers[i].image; + + err = vkCreateImageView(device, &color_attachment_view, NULL, &Kore::Vulkan::buffers[i].view); + assert(!err); + } + + current_buffer = 0; + + if (NULL != presentModes) { + free(presentModes); + } + + const VkFormat depth_format = VK_FORMAT_D16_UNORM; + + if (depthBits > 0) { + VkImageCreateInfo image = {}; + image.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + image.pNext = NULL; + image.imageType = VK_IMAGE_TYPE_2D; + image.format = depth_format; + image.extent.width = renderTargetWidth; + image.extent.height = renderTargetHeight; + image.extent.depth = 1; + image.mipLevels = 1; + image.arrayLayers = 1; + image.samples = VK_SAMPLE_COUNT_1_BIT; + image.tiling = VK_IMAGE_TILING_OPTIMAL; + image.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + image.flags = 0; + + VkMemoryAllocateInfo mem_alloc = {}; + mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + mem_alloc.pNext = NULL; + mem_alloc.allocationSize = 0; + mem_alloc.memoryTypeIndex = 0; + + VkImageViewCreateInfo view = {}; + view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + view.pNext = NULL; + view.image = VK_NULL_HANDLE; + view.format = depth_format; + view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; + view.subresourceRange.baseMipLevel = 0; + view.subresourceRange.levelCount = 1; + view.subresourceRange.baseArrayLayer = 0; + view.subresourceRange.layerCount = 1; + view.flags = 0; + view.viewType = VK_IMAGE_VIEW_TYPE_2D; + + VkMemoryRequirements mem_reqs = {}; + bool pass; + + /* create image */ + err = vkCreateImage(device, &image, NULL, &Kore::Vulkan::depth.image); + assert(!err); + + /* get memory requirements for this object */ + vkGetImageMemoryRequirements(device, Kore::Vulkan::depth.image, &mem_reqs); + + /* select memory size and type */ + mem_alloc.allocationSize = mem_reqs.size; + pass = memory_type_from_properties(mem_reqs.memoryTypeBits, 0, /* No requirements */ &mem_alloc.memoryTypeIndex); + assert(pass); + + /* allocate memory */ + err = vkAllocateMemory(device, &mem_alloc, NULL, &Kore::Vulkan::depth.mem); + assert(!err); + + /* bind memory */ + err = vkBindImageMemory(device, Kore::Vulkan::depth.image, Kore::Vulkan::depth.mem, 0); + assert(!err); + + set_image_layout(Kore::Vulkan::depth.image, VK_IMAGE_ASPECT_DEPTH_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + + /* create image view */ + view.image = Kore::Vulkan::depth.image; + err = vkCreateImageView(device, &view, NULL, &Kore::Vulkan::depth.view); + assert(!err); + } + + VkAttachmentDescription attachments[2]; + attachments[0].format = format; + attachments[0].samples = VK_SAMPLE_COUNT_1_BIT; + attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; + attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attachments[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + attachments[0].flags = 0; + + if (depthBits > 0) { + attachments[1].format = depth_format; + attachments[1].samples = VK_SAMPLE_COUNT_1_BIT; + attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE; + attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attachments[1].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + attachments[1].flags = 0; + } + + VkAttachmentReference color_reference = {}; + color_reference.attachment = 0; + color_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + VkAttachmentReference depth_reference = {}; + depth_reference.attachment = 1; + depth_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + VkSubpassDescription subpass = {}; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.flags = 0; + subpass.inputAttachmentCount = 0; + subpass.pInputAttachments = nullptr; + subpass.colorAttachmentCount = 1; + subpass.pColorAttachments = &color_reference; + subpass.pResolveAttachments = nullptr; + subpass.pDepthStencilAttachment = depthBits > 0 ? &depth_reference : nullptr; + subpass.preserveAttachmentCount = 0; + subpass.pPreserveAttachments = nullptr; + + VkSubpassDependency dependencies[2]; + memset(&dependencies, 0, sizeof(dependencies)); + + // for the frame-buffer + dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; + dependencies[0].dstSubpass = 0; + dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; + dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + + dependencies[1].srcSubpass = 0; + dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; + dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; + dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + + VkRenderPassCreateInfo rp_info = {}; + rp_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + rp_info.pNext = nullptr; + rp_info.attachmentCount = depthBits > 0 ? 2 : 1; + rp_info.pAttachments = attachments; + rp_info.subpassCount = 1; + rp_info.pSubpasses = &subpass; + rp_info.dependencyCount = 2; + rp_info.pDependencies = dependencies; + + err = vkCreateRenderPass(device, &rp_info, NULL, &framebuffer_render_pass); + assert(!err); + + VkImageView attachmentViews[2]; + + if (depthBits > 0) { + attachmentViews[1] = Kore::Vulkan::depth.view; + } + + VkFramebufferCreateInfo fb_info = {}; + fb_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + fb_info.pNext = NULL; + fb_info.renderPass = framebuffer_render_pass; + fb_info.attachmentCount = depthBits > 0 ? 2 : 1; + fb_info.pAttachments = attachmentViews; + fb_info.width = renderTargetWidth; + fb_info.height = renderTargetHeight; + fb_info.layers = 1; + + framebuffers = (VkFramebuffer *)malloc(swapchainImageCount * sizeof(VkFramebuffer)); + assert(framebuffers); + + for (uint32_t i = 0; i < swapchainImageCount; i++) { + attachmentViews[0] = Kore::Vulkan::buffers[i].view; + err = vkCreateFramebuffer(device, &fb_info, NULL, &framebuffers[i]); + assert(!err); + } + + flush_init_cmd(); +} + +void create_render_target_render_pass(void) { + VkAttachmentDescription attachments[2]; + attachments[0].format = VK_FORMAT_B8G8R8A8_UNORM; // target->impl.format; // TODO + attachments[0].samples = VK_SAMPLE_COUNT_1_BIT; + attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; + attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attachments[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + attachments[0].flags = 0; + + // TODO + /*if (depthBufferBits > 0) { + attachments[1].format = VK_FORMAT_D16_UNORM; + attachments[1].samples = VK_SAMPLE_COUNT_1_BIT; + attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE; + attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + attachments[1].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + attachments[1].flags = 0; + }*/ + + VkAttachmentReference color_reference = {0}; + color_reference.attachment = 0; + color_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + VkAttachmentReference depth_reference = {0}; + depth_reference.attachment = 1; + depth_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + + VkSubpassDescription subpass = {0}; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.flags = 0; + subpass.inputAttachmentCount = 0; + subpass.pInputAttachments = NULL; + subpass.colorAttachmentCount = 1; + subpass.pColorAttachments = &color_reference; + subpass.pResolveAttachments = NULL; + subpass.pDepthStencilAttachment = /*depthBufferBits > 0 ? &depth_reference :*/ NULL; // TODO + subpass.preserveAttachmentCount = 0; + subpass.pPreserveAttachments = NULL; + + // for render-targets + VkSubpassDependency dependencies[2]; + memset(&dependencies, 0, sizeof(dependencies)); + + dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; + dependencies[0].dstSubpass = 0; + dependencies[0].srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependencies[0].srcAccessMask = VK_ACCESS_SHADER_READ_BIT; + dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + + dependencies[1].srcSubpass = 0; + dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; + dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependencies[1].dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dependencies[1].dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + + VkRenderPassCreateInfo rp_info = {}; + rp_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + rp_info.pNext = NULL; + rp_info.attachmentCount = /*depthBufferBits > 0 ? 2 :*/ 1; // TODO + rp_info.pAttachments = attachments; + rp_info.subpassCount = 1; + rp_info.pSubpasses = &subpass; + rp_info.dependencyCount = 2; + rp_info.pDependencies = dependencies; + + VkResult err = vkCreateRenderPass(device, &rp_info, NULL, &rendertarget_render_pass); + assert(!err); +} + void kinc_g5_init(int window, int depthBufferBits, int stencilBufferBits, bool vsync) { + depthBits = depthBufferBits; + stencilBits = stencilBufferBits; + vsynced = vsync; uint32_t instance_extension_count = 0; uint32_t instance_layer_count = 0; #ifdef VALIDATE uint32_t device_validation_layer_count = 0; #endif - // demo->enabled_extension_count = 0; - // demo->enabled_layer_count = 0; #ifdef VALIDATE - char *instance_validation_layers[] = {"VK_LAYER_LUNARG_standard_validation"}; + char *instance_validation_layers[] = {"VK_LAYER_KHRONOS_validation"}; #endif #ifdef VALIDATE - device_validation_layers[0] = "VK_LAYER_LUNARG_standard_validation"; + device_validation_layers[0] = "VK_LAYER_KHRONOS_validation"; device_validation_layer_count = 1; #endif @@ -255,7 +656,7 @@ void kinc_g5_init(int window, int depthBufferBits, int stencilBufferBits, bool v assert(!err); #ifdef VALIDATE - validation_found = demo_check_layers(ARRAY_SIZE(instance_validation_layers), instance_validation_layers, instance_layer_count, instance_layers); + validation_found = check_layers(ARRAY_SIZE(instance_validation_layers), instance_validation_layers, instance_layer_count, instance_layers); enabled_layer_count = ARRAY_SIZE(instance_validation_layers); #endif free(instance_layers); @@ -273,32 +674,24 @@ void kinc_g5_init(int window, int depthBufferBits, int stencilBufferBits, bool v VkExtensionProperties *instance_extensions = (VkExtensionProperties *)malloc(sizeof(VkExtensionProperties) * instance_extension_count); err = vkEnumerateInstanceExtensionProperties(nullptr, &instance_extension_count, instance_extensions); assert(!err); - for (uint32_t i = 0; i < instance_extension_count; i++) { - if (!strcmp(VK_KHR_SURFACE_EXTENSION_NAME, instance_extensions[i].extensionName)) { - surfaceExtFound = 1; - extension_names[enabled_extension_count++] = VK_KHR_SURFACE_EXTENSION_NAME; - } -#ifdef KORE_WINDOWS - if (!strcmp(VK_KHR_WIN32_SURFACE_EXTENSION_NAME, instance_extensions[i].extensionName)) { - platformSurfaceExtFound = 1; - extension_names[enabled_extension_count++] = VK_KHR_WIN32_SURFACE_EXTENSION_NAME; - } -#else - if (!strcmp(VK_KHR_XCB_SURFACE_EXTENSION_NAME, instance_extensions[i].extensionName)) { - platformSurfaceExtFound = 1; - extension_names[enabled_extension_count++] = VK_KHR_XCB_SURFACE_EXTENSION_NAME; - } -#endif - - if (!strcmp(VK_EXT_DEBUG_REPORT_EXTENSION_NAME, instance_extensions[i].extensionName)) { + for (uint32_t i = 0; i < instance_extension_count; i++) { + if (!strcmp(VK_KHR_SURFACE_EXTENSION_NAME, instance_extensions[i].extensionName)) { + surfaceExtFound = 1; + extension_names[enabled_extension_count++] = VK_KHR_SURFACE_EXTENSION_NAME; + } + if (!strcmp(KINC_SURFACE_EXT_NAME, instance_extensions[i].extensionName)) { + platformSurfaceExtFound = 1; + extension_names[enabled_extension_count++] = KINC_SURFACE_EXT_NAME; + } + if (!strcmp(VK_EXT_DEBUG_REPORT_EXTENSION_NAME, instance_extensions[i].extensionName)) { #ifdef VALIDATE - extension_names[enabled_extension_count++] = VK_EXT_DEBUG_REPORT_EXTENSION_NAME; + extension_names[enabled_extension_count++] = VK_EXT_DEBUG_REPORT_EXTENSION_NAME; #endif - } - assert(enabled_extension_count < 64); - } + } + assert(enabled_extension_count < 64); + } - free(instance_extensions); + free(instance_extensions); } if (!surfaceExtFound) { @@ -310,21 +703,12 @@ void kinc_g5_init(int window, int depthBufferBits, int stencilBufferBits, bool v "vkCreateInstance Failure"); } if (!platformSurfaceExtFound) { -#ifdef KORE_WINDOWS - ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find " - "the " VK_KHR_WIN32_SURFACE_EXTENSION_NAME " extension.\n\nDo you have a compatible " - "Vulkan installable client driver (ICD) installed?\nPlease " - "look at the Getting Started guide for additional " - "information.\n", - "vkCreateInstance Failure"); -#else - ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find " - "the " VK_KHR_XCB_SURFACE_EXTENSION_NAME " extension.\n\nDo you have a compatible " - "Vulkan installable client driver (ICD) installed?\nPlease " - "look at the Getting Started guide for additional " - "information.\n", - "vkCreateInstance Failure"); -#endif + ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find " + "the " KINC_SURFACE_EXT_NAME " extension.\n\nDo you have a compatible " + "Vulkan installable client driver (ICD) installed?\nPlease " + "look at the Getting Started guide for additional " + "information.\n", + "vkCreateInstance Failure"); } VkApplicationInfo app = {}; app.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; @@ -333,7 +717,11 @@ void kinc_g5_init(int window, int depthBufferBits, int stencilBufferBits, bool v app.applicationVersion = 0; app.pEngineName = "Kore"; app.engineVersion = 0; +#ifdef KORE_VKRT + app.apiVersion = VK_API_VERSION_1_2; +#else app.apiVersion = VK_API_VERSION_1_0; +#endif VkInstanceCreateInfo info = {}; info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; @@ -351,11 +739,16 @@ void kinc_g5_init(int window, int depthBufferBits, int stencilBufferBits, bool v uint32_t gpu_count; - allocator.pfnAllocation = myalloc; + +#ifndef KORE_ANDROID + allocator.pfnAllocation = myalloc; allocator.pfnFree = myfree; allocator.pfnReallocation = myrealloc; - err = vkCreateInstance(&info, &allocator, &inst); +#else + err = vkCreateInstance(&info, NULL, &inst); +#endif + if (err == VK_ERROR_INCOMPATIBLE_DRIVER) { ERR_EXIT("Cannot find a compatible Vulkan installable client driver " "(ICD).\n\nPlease look at the Getting Started guide for " @@ -409,7 +802,7 @@ void kinc_g5_init(int window, int depthBufferBits, int stencilBufferBits, bool v assert(!err); #ifdef VALIDATE - validation_found = demo_check_layers(device_validation_layer_count, device_validation_layers, device_layer_count, device_layers); + validation_found = check_layers(device_validation_layer_count, device_validation_layers, device_layer_count, device_layers); enabled_layer_count = device_validation_layer_count; #endif @@ -435,6 +828,33 @@ void kinc_g5_init(int window, int depthBufferBits, int stencilBufferBits, bool v swapchainExtFound = 1; extension_names[enabled_extension_count++] = VK_KHR_SWAPCHAIN_EXTENSION_NAME; } + if (!strcmp(VK_KHR_MAINTENANCE1_EXTENSION_NAME, device_extensions[i].extensionName)) { + // Allows negative viewport height to flip viewport + extension_names[enabled_extension_count++] = VK_KHR_MAINTENANCE1_EXTENSION_NAME; + } +#ifdef KORE_VKRT + if (!strcmp(VK_KHR_RAY_TRACING_EXTENSION_NAME, device_extensions[i].extensionName)) { + extension_names[enabled_extension_count++] = VK_KHR_RAY_TRACING_EXTENSION_NAME; + } + if (!strcmp(VK_KHR_MAINTENANCE3_EXTENSION_NAME, device_extensions[i].extensionName)) { + extension_names[enabled_extension_count++] = VK_KHR_MAINTENANCE3_EXTENSION_NAME; + } + if (!strcmp(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME, device_extensions[i].extensionName)) { + extension_names[enabled_extension_count++] = VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME; + } + if (!strcmp(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME, device_extensions[i].extensionName)) { + extension_names[enabled_extension_count++] = VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME; + } + if (!strcmp(VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME, device_extensions[i].extensionName)) { + extension_names[enabled_extension_count++] = VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME; + } + if (!strcmp(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME, device_extensions[i].extensionName)) { + extension_names[enabled_extension_count++] = VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME; + } + if (!strcmp(VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME, device_extensions[i].extensionName)) { + extension_names[enabled_extension_count++] = VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME; + } +#endif assert(enabled_extension_count < 64); } @@ -495,38 +915,17 @@ void kinc_g5_init(int window, int depthBufferBits, int stencilBufferBits, bool v vkGetPhysicalDeviceQueueFamilyProperties(gpu, &queue_count, queue_props); assert(queue_count >= 1); - width = kinc_window_width(window); - height = kinc_window_height(window); - -#ifdef KORE_WINDOWS - windowHandle = (HWND)kinc_windows_window_handle(window); - ShowWindow(windowHandle, SW_SHOW); - SetForegroundWindow(windowHandle); // Slightly Higher Priority - SetFocus(windowHandle); // Sets Keyboard Focus To The Window -#endif + newRenderTargetWidth = kinc_window_width(window); + newRenderTargetHeight = kinc_window_height(window); { VkResult err; uint32_t i; -#ifdef KORE_WINDOWS - VkWin32SurfaceCreateInfoKHR createInfo = {}; - createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; - createInfo.pNext = NULL; - createInfo.flags = 0; - createInfo.hinstance = connection; - createInfo.hwnd = windowHandle; - err = vkCreateWin32SurfaceKHR(inst, &createInfo, NULL, &surface); - assert(!err); -#else - VkXcbSurfaceCreateInfoKHR createInfo; - createInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR; - createInfo.pNext = nullptr; - createInfo.flags = 0; - createInfo.connection = connection; - createInfo.window = window; - err = vkCreateXcbSurfaceKHR(inst, &createInfo, nullptr, &surface); - assert(!err); -#endif + err = kinc_vulkan_create_surface(inst, window, &surface); + assert(!err); + + has_surface = true; + // Iterate over each queue to learn whether it supports presenting: VkBool32 *supportsPresent = (VkBool32 *)malloc(queue_count * sizeof(VkBool32)); for (i = 0; i < queue_count; i++) { @@ -602,6 +1001,24 @@ void kinc_g5_init(int window, int depthBufferBits, int stencilBufferBits, bool v deviceinfo.enabledExtensionCount = enabled_extension_count; deviceinfo.ppEnabledExtensionNames = (const char *const *)extension_names; +#ifdef KORE_VKRT + VkPhysicalDeviceRayTracingFeaturesKHR rayTracingExt = {}; + rayTracingExt.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_FEATURES_KHR; + rayTracingExt.pNext = nullptr; + rayTracingExt.rayTracing = VK_TRUE; + + VkPhysicalDeviceBufferDeviceAddressFeatures bufferDeviceAddressExt = {}; + bufferDeviceAddressExt.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES; + bufferDeviceAddressExt.pNext = &rayTracingExt; + bufferDeviceAddressExt.bufferDeviceAddress = VK_TRUE; + + VkPhysicalDeviceFeatures2KHR physical_device_features = {}; + physical_device_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR; + physical_device_features.pNext = &bufferDeviceAddressExt; + + deviceinfo.pNext = &physical_device_features; +#endif + err = vkCreateDevice(gpu, &deviceinfo, nullptr, &device); assert(!err); } @@ -640,286 +1057,10 @@ void kinc_g5_init(int window, int depthBufferBits, int stencilBufferBits, bool v err = vkCreateCommandPool(device, &cmd_pool_info, NULL, &cmd_pool); assert(!err); - VkSwapchainKHR oldSwapchain = swapchain; - - // Check the surface capabilities and formats - VkSurfaceCapabilitiesKHR surfCapabilities = {}; - err = fpGetPhysicalDeviceSurfaceCapabilitiesKHR(gpu, surface, &surfCapabilities); - assert(!err); - - uint32_t presentModeCount; - err = fpGetPhysicalDeviceSurfacePresentModesKHR(gpu, surface, &presentModeCount, NULL); - assert(!err); - VkPresentModeKHR *presentModes = (VkPresentModeKHR *)malloc(presentModeCount * sizeof(VkPresentModeKHR)); - assert(presentModes); - err = fpGetPhysicalDeviceSurfacePresentModesKHR(gpu, surface, &presentModeCount, presentModes); - assert(!err); - - VkExtent2D swapchainExtent; - // width and height are either both -1, or both not -1. - if (surfCapabilities.currentExtent.width == (uint32_t)-1) { - // If the surface size is undefined, the size is set to - // the size of the images requested. - swapchainExtent.width = width; - swapchainExtent.height = height; - } - else { - // If the surface size is defined, the swap chain size must match - swapchainExtent = surfCapabilities.currentExtent; - width = surfCapabilities.currentExtent.width; - height = surfCapabilities.currentExtent.height; - } - - VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR; - - // Determine the number of VkImage's to use in the swap chain (we desire to - // own only 1 image at a time, besides the images being displayed and - // queued for display): - uint32_t desiredNumberOfSwapchainImages = surfCapabilities.minImageCount + 1; - if ((surfCapabilities.maxImageCount > 0) && (desiredNumberOfSwapchainImages > surfCapabilities.maxImageCount)) { - // Application must settle for fewer images than desired: - desiredNumberOfSwapchainImages = surfCapabilities.maxImageCount; - } - - VkSurfaceTransformFlagBitsKHR preTransform = {}; - if (surfCapabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) { - preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; - } - else { - preTransform = surfCapabilities.currentTransform; - } - - VkSwapchainCreateInfoKHR swapchain_info = {}; - swapchain_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; - swapchain_info.pNext = NULL; - swapchain_info.surface = surface; - swapchain_info.minImageCount = desiredNumberOfSwapchainImages; - swapchain_info.imageFormat = format; - swapchain_info.imageColorSpace = color_space; - swapchain_info.imageExtent.width = swapchainExtent.width; - swapchain_info.imageExtent.height = swapchainExtent.height; - swapchain_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - swapchain_info.preTransform = preTransform; - swapchain_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; - swapchain_info.imageArrayLayers = 1; - swapchain_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; - swapchain_info.queueFamilyIndexCount = 0; - swapchain_info.pQueueFamilyIndices = NULL; - swapchain_info.presentMode = swapchainPresentMode; - swapchain_info.oldSwapchain = oldSwapchain; - swapchain_info.clipped = true; - - uint32_t i; - - err = fpCreateSwapchainKHR(device, &swapchain_info, NULL, &swapchain); - assert(!err); - - // If we just re-created an existing swapchain, we should destroy the old - // swapchain at this point. - // Note: destroying the swapchain also cleans up all its associated - // presentable images once the platform is done with them. - if (oldSwapchain != VK_NULL_HANDLE) { - fpDestroySwapchainKHR(device, oldSwapchain, NULL); - } - - err = fpGetSwapchainImagesKHR(device, swapchain, &swapchainImageCount, NULL); - assert(!err); - - VkImage *swapchainImages = (VkImage *)malloc(swapchainImageCount * sizeof(VkImage)); - assert(swapchainImages); - err = fpGetSwapchainImagesKHR(device, swapchain, &swapchainImageCount, swapchainImages); - assert(!err); - - Kore::Vulkan::buffers = (Kore::Vulkan::SwapchainBuffers *)malloc(sizeof(Kore::Vulkan::SwapchainBuffers) * swapchainImageCount); - assert(Kore::Vulkan::buffers); - - for (i = 0; i < swapchainImageCount; i++) { - VkImageViewCreateInfo color_attachment_view = {}; - color_attachment_view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - color_attachment_view.pNext = NULL; - color_attachment_view.format = format; - color_attachment_view.components.r = VK_COMPONENT_SWIZZLE_R; - color_attachment_view.components.g = VK_COMPONENT_SWIZZLE_G; - color_attachment_view.components.b = VK_COMPONENT_SWIZZLE_B; - color_attachment_view.components.a = VK_COMPONENT_SWIZZLE_A; - color_attachment_view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - color_attachment_view.subresourceRange.baseMipLevel = 0; - color_attachment_view.subresourceRange.levelCount = 1; - color_attachment_view.subresourceRange.baseArrayLayer = 0; - color_attachment_view.subresourceRange.layerCount = 1; - color_attachment_view.viewType = VK_IMAGE_VIEW_TYPE_2D; - color_attachment_view.flags = 0; - - Kore::Vulkan::buffers[i].image = swapchainImages[i]; - - // Render loop will expect image to have been used before and in - // VK_IMAGE_LAYOUT_PRESENT_SRC_KHR - // layout and will change to COLOR_ATTACHMENT_OPTIMAL, so init the image - // to that state - Kore::Vulkan::demo_set_image_layout(Kore::Vulkan::buffers[i].image, VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); - - color_attachment_view.image = Kore::Vulkan::buffers[i].image; - - err = vkCreateImageView(device, &color_attachment_view, NULL, &Kore::Vulkan::buffers[i].view); - assert(!err); - } - - current_buffer = 0; - - if (NULL != presentModes) { - free(presentModes); - } - - const VkFormat depth_format = VK_FORMAT_D16_UNORM; - VkImageCreateInfo image = {}; - image.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; - image.pNext = NULL; - image.imageType = VK_IMAGE_TYPE_2D; - image.format = depth_format; - image.extent.width = width; - image.extent.height = height; - image.extent.depth = 1; - image.mipLevels = 1; - image.arrayLayers = 1; - image.samples = VK_SAMPLE_COUNT_1_BIT; - image.tiling = VK_IMAGE_TILING_OPTIMAL; - image.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - image.flags = 0; - - VkMemoryAllocateInfo mem_alloc = {}; - mem_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - mem_alloc.pNext = NULL; - mem_alloc.allocationSize = 0; - mem_alloc.memoryTypeIndex = 0; - - VkImageViewCreateInfo view = {}; - view.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - view.pNext = NULL; - view.image = VK_NULL_HANDLE; - view.format = depth_format; - view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - view.subresourceRange.baseMipLevel = 0; - view.subresourceRange.levelCount = 1; - view.subresourceRange.baseArrayLayer = 0; - view.subresourceRange.layerCount = 1; - view.flags = 0; - view.viewType = VK_IMAGE_VIEW_TYPE_2D; - - VkMemoryRequirements mem_reqs = {}; - bool pass; - - ::depth_format = depth_format; - - /* create image */ - err = vkCreateImage(device, &image, NULL, &Kore::Vulkan::depth.image); - assert(!err); - - /* get memory requirements for this object */ - vkGetImageMemoryRequirements(device, Kore::Vulkan::depth.image, &mem_reqs); - - /* select memory size and type */ - mem_alloc.allocationSize = mem_reqs.size; - pass = memory_type_from_properties(mem_reqs.memoryTypeBits, 0, /* No requirements */ &mem_alloc.memoryTypeIndex); - assert(pass); - - /* allocate memory */ - err = vkAllocateMemory(device, &mem_alloc, NULL, &Kore::Vulkan::depth.mem); - assert(!err); - - /* bind memory */ - err = vkBindImageMemory(device, Kore::Vulkan::depth.image, Kore::Vulkan::depth.mem, 0); - assert(!err); - - Kore::Vulkan::demo_set_image_layout(Kore::Vulkan::depth.image, VK_IMAGE_ASPECT_DEPTH_BIT, VK_IMAGE_LAYOUT_UNDEFINED, - VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); - - /* create image view */ - view.image = Kore::Vulkan::depth.image; - err = vkCreateImageView(device, &view, NULL, &Kore::Vulkan::depth.view); - assert(!err); - - VkAttachmentDescription attachments[2]; - attachments[0].format = format; - attachments[0].samples = VK_SAMPLE_COUNT_1_BIT; - attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - attachments[0].flags = 0; - - attachments[1].format = depth_format; - attachments[1].samples = VK_SAMPLE_COUNT_1_BIT; - attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments[1].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - attachments[1].flags = 0; - - VkAttachmentReference color_reference = {}; - color_reference.attachment = 0; - color_reference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - VkAttachmentReference depth_reference = {}; - depth_reference.attachment = 1; - depth_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkSubpassDescription subpass = {}; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.flags = 0; - subpass.inputAttachmentCount = 0; - subpass.pInputAttachments = nullptr; - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = &color_reference; - subpass.pResolveAttachments = nullptr; - subpass.pDepthStencilAttachment = &depth_reference; - subpass.preserveAttachmentCount = 0; - subpass.pPreserveAttachments = nullptr; - - VkRenderPassCreateInfo rp_info = {}; - rp_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - rp_info.pNext = nullptr; - rp_info.attachmentCount = 2; - rp_info.pAttachments = attachments; - rp_info.subpassCount = 1; - rp_info.pSubpasses = &subpass; - rp_info.dependencyCount = 0; - rp_info.pDependencies = nullptr; - - err = vkCreateRenderPass(device, &rp_info, NULL, &render_pass); - assert(!err); - - { - VkImageView attachments[2]; - attachments[1] = Kore::Vulkan::depth.view; - - VkFramebufferCreateInfo fb_info = {}; - fb_info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - fb_info.pNext = NULL; - fb_info.renderPass = render_pass; - fb_info.attachmentCount = 2; - fb_info.pAttachments = attachments; - fb_info.width = width; - fb_info.height = height; - fb_info.layers = 1; - - uint32_t i; - - framebuffers = (VkFramebuffer *)malloc(swapchainImageCount * sizeof(VkFramebuffer)); - assert(framebuffers); + create_swapchain(); + create_render_target_render_pass(); - for (i = 0; i < swapchainImageCount; i++) { - attachments[0] = Kore::Vulkan::buffers[i].view; - err = vkCreateFramebuffer(device, &fb_info, NULL, &framebuffers[i]); - assert(!err); - } - } - - Kore::Vulkan::demo_flush_init_cmd(); + createDescriptorLayout(); began = false; kinc_g5_begin(nullptr, 0); @@ -941,12 +1082,18 @@ bool kinc_g5_swap_buffers() { void kinc_g5_begin(kinc_g5_render_target_t *renderTarget, int window) { if (renderTarget != nullptr) { - renderTarget->impl.renderPass = render_pass; renderTarget->impl.framebuffer = framebuffers[current_buffer]; } if (began) return; + if (newRenderTargetWidth != renderTargetWidth || newRenderTargetHeight != renderTargetHeight) { + renderTargetWidth = newRenderTargetWidth; + renderTargetHeight = newRenderTargetHeight; + vkDeviceWaitIdle(device); + create_swapchain(); + } + VkSemaphoreCreateInfo presentCompleteSemaphoreCreateInfo = {}; presentCompleteSemaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; presentCompleteSemaphoreCreateInfo.pNext = NULL; @@ -958,23 +1105,6 @@ void kinc_g5_begin(kinc_g5_render_target_t *renderTarget, int window) { // Get the index of the next available swapchain image: err = fpAcquireNextImageKHR(device, swapchain, UINT64_MAX, presentCompleteSemaphore, (VkFence)0, // TODO: Show use of fence ¤t_buffer); - /*if (err == VK_ERROR_OUT_OF_DATE_KHR) { - // demo->swapchain is out of date (e.g. the window was resized) and - // must be recreated: - // demo_resize(demo); - // demo_draw(demo); - error("VK_ERROR_OUT_OF_DATE_KHR"); - vkDestroySemaphore(device, presentCompleteSemaphore, NULL); - return; - } - else if (err == VK_SUBOPTIMAL_KHR) { - // demo->swapchain is not as optimal as it could be, but the platform's - // presentation engine will still present the image correctly. - } - else { - assert(!err); - }*/ - assert(!err); began = true; } @@ -986,17 +1116,31 @@ void kinc_g5_end(int window) { void kinc_g5_set_texture(kinc_g5_texture_unit_t unit, kinc_g5_texture_t *texture) { vulkanTextures[unit.impl.binding - 2] = texture; vulkanRenderTargets[unit.impl.binding - 2] = nullptr; - //** if (PipelineState5Impl::current != nullptr) - //** vkCmdBindDescriptorSets(draw_cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, PipelineState5Impl::current->pipeline_layout, 0, 1, &texture->desc_set, 0, NULL); } void kinc_g5_set_image_texture(kinc_g5_texture_unit_t unit, kinc_g5_texture_t *texture) {} void kinc_g5_set_texture_addressing(kinc_g5_texture_unit_t unit, kinc_g5_texture_direction_t dir, kinc_g5_texture_addressing_t addressing) {} -void kinc_g5_set_texture_magnification_filter(kinc_g5_texture_unit_t texunit, kinc_g5_texture_filter_t filter) {} +bool kinc_vulkan_internal_bilinear = false; -void kinc_g5_set_texture_minification_filter(kinc_g5_texture_unit_t texunit, kinc_g5_texture_filter_t filter) {} +void kinc_g5_set_texture_magnification_filter(kinc_g5_texture_unit_t texunit, kinc_g5_texture_filter_t filter) { + if (filter == KINC_G5_TEXTURE_FILTER_POINT) { + kinc_vulkan_internal_bilinear = false; + } + else { + kinc_vulkan_internal_bilinear = true; + } +} + +void kinc_g5_set_texture_minification_filter(kinc_g5_texture_unit_t texunit, kinc_g5_texture_filter_t filter) { + if (filter == KINC_G5_TEXTURE_FILTER_POINT) { + kinc_vulkan_internal_bilinear = false; + } + else { + kinc_vulkan_internal_bilinear = true; + } +} void kinc_g5_set_texture_mipmap_filter(kinc_g5_texture_unit_t texunit, kinc_g5_mipmap_filter_t filter) {} @@ -1010,56 +1154,8 @@ int kinc_g5_max_bound_textures(void) { return props.limits.maxPerStageDescriptorSamplers; } -/*void Graphics5::restoreRenderTarget() { - if (onBackBuffer) return; - - endPass(); - - currentRenderTarget = nullptr; - onBackBuffer = true; - - VkClearValue clear_values[2]; - memset(clear_values, 0, sizeof(VkClearValue) * 2); - clear_values[0].color.float32[0] = 0.0f; - clear_values[0].color.float32[1] = 0.0f; - clear_values[0].color.float32[2] = 0.0f; - clear_values[0].color.float32[3] = 1.0f; - clear_values[1].depthStencil.depth = depthStencil; - clear_values[1].depthStencil.stencil = 0; - - VkRenderPassBeginInfo rp_begin = {}; - rp_begin.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - rp_begin.pNext = nullptr; - rp_begin.renderPass = render_pass; - rp_begin.framebuffer = framebuffers[current_buffer]; - rp_begin.renderArea.offset.x = 0; - rp_begin.renderArea.offset.y = 0; - rp_begin.renderArea.extent.width = width; - rp_begin.renderArea.extent.height = height; - rp_begin.clearValueCount = 2; - rp_begin.pClearValues = clear_values; - - vkCmdBeginRenderPass(draw_cmd, &rp_begin, VK_SUBPASS_CONTENTS_INLINE); - - VkViewport viewport; - memset(&viewport, 0, sizeof(viewport)); - viewport.width = (float)width; - viewport.height = (float)height; - viewport.minDepth = (float)0.0f; - viewport.maxDepth = (float)1.0f; - vkCmdSetViewport(draw_cmd, 0, 1, &viewport); - - VkRect2D scissor; - memset(&scissor, 0, sizeof(scissor)); - scissor.extent.width = width; - scissor.extent.height = height; - scissor.offset.x = 0; - scissor.offset.y = 0; - vkCmdSetScissor(draw_cmd, 0, 1, &scissor); -}*/ - bool kinc_g5_render_targets_inverted_y() { - return true; + return false; } bool kinc_g5_non_pow2_textures_qupported() { @@ -1081,3 +1177,17 @@ bool kinc_g5_are_query_results_available(unsigned occlusionQuery) { } void kinc_g5_get_query_result(unsigned occlusionQuery, unsigned *pixelCount) {} + +bool kinc_vulkan_internal_get_size(int *width, int *height) { + if (has_surface) { + VkSurfaceCapabilitiesKHR capabilities; + VkResult err = fpGetPhysicalDeviceSurfaceCapabilitiesKHR(gpu, surface, &capabilities); + assert(!err); + *width = capabilities.currentExtent.width; + *height = capabilities.currentExtent.height; + return true; + } + else { + return false; + } +} diff --git a/Backends/Graphics5/Vulkan/Sources/Kore/Vulkan.h b/Backends/Graphics5/Vulkan/Sources/Kore/Vulkan.h index c4522f012..a48751cb8 100644 --- a/Backends/Graphics5/Vulkan/Sources/Kore/Vulkan.h +++ b/Backends/Graphics5/Vulkan/Sources/Kore/Vulkan.h @@ -5,8 +5,6 @@ #include #include -struct PipelineState5Impl_s; - namespace Kore { namespace Vulkan { struct SwapchainBuffers { @@ -28,9 +26,5 @@ namespace Kore { // buffer hack extern VkBuffer* vertexUniformBuffer; extern VkBuffer* fragmentUniformBuffer; - - void demo_set_image_layout(VkImage image, VkImageAspectFlags aspectMask, VkImageLayout old_image_layout, VkImageLayout new_image_layout); - void demo_flush_init_cmd(); - void createDescriptorSet(struct PipelineState5Impl_s *pipeline, kinc_g5_texture_t *texture, kinc_g5_render_target_t *renderTarget, VkDescriptorSet &desc_set); } } diff --git a/Backends/System/Android/Sources/Kore/System.cpp b/Backends/System/Android/Sources/Kore/System.cpp index 994b4b930..9c184f507 100644 --- a/Backends/System/Android/Sources/Kore/System.cpp +++ b/Backends/System/Android/Sources/Kore/System.cpp @@ -17,6 +17,9 @@ #include #include +#include +#include + void pauseAudio(); void resumeAudio(); @@ -36,23 +39,43 @@ namespace { bool paused = true; bool displayIsInitialized = false; bool appIsForeground = false; + bool activityJustResized = false; +} + +#ifdef KORE_VULKAN +#include +extern "C" VkResult kinc_vulkan_create_surface(VkInstance instance, int window_index, VkSurfaceKHR *surface) { + assert(app->window != NULL); + VkAndroidSurfaceCreateInfoKHR createInfo = {}; + createInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR; + createInfo.pNext = NULL; + createInfo.flags = 0; + createInfo.window = app->window; + return vkCreateAndroidSurfaceKHR(instance, &createInfo, NULL, surface); } +#endif void androidSwapBuffers() { +#ifndef KORE_VULKAN if (glContext->Swap() != EGL_SUCCESS) { kinc_log(KINC_LOG_LEVEL_WARNING, "GL context lost."); } +#endif } namespace { void initDisplay() { +#ifndef KORE_VULKAN if (glContext->Resume(app->window) != EGL_SUCCESS) { kinc_log(KINC_LOG_LEVEL_WARNING, "GL context lost."); } +#endif } void termDisplay() { +#ifndef KORE_VULKAN glContext->Suspend(); +#endif } void updateAppForegroundStatus(bool displayIsInitializedValue, bool appIsForegroundValue) { @@ -135,6 +158,15 @@ namespace { } } + float last_x = 0.0f; + float last_y = 0.0f; + float last_l = 0.0f; + float last_r = 0.0f; + bool last_hat_left = false; + bool last_hat_right = false; + bool last_hat_up = false; + bool last_hat_down = false; + int32_t input(android_app* app, AInputEvent* event) { if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) { int source = AInputEvent_getSource(event); @@ -144,11 +176,74 @@ namespace { return 1; } else if ((source & AINPUT_SOURCE_JOYSTICK) == AINPUT_SOURCE_JOYSTICK) { - float x = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_X, 0); - float y = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_Y, 0); // int id = AInputEvent_getDeviceId(event); - kinc_internal_gamepad_trigger_axis(0, 0, x); - kinc_internal_gamepad_trigger_axis(0, 1, y); + + float x = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_X, 0); + if (x != last_x) { + kinc_internal_gamepad_trigger_axis(0, 0, x); + last_x = x; + } + + float y = -AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_Y, 0); + if (y != last_y) { + kinc_internal_gamepad_trigger_axis(0, 1, y); + last_y = y; + } + + float l = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_LTRIGGER, 0); + if (l != last_l) { + kinc_internal_gamepad_trigger_button(0, 6, l); + last_l = l; + } + + float r = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_RTRIGGER, 0); + if (r != last_r) { + kinc_internal_gamepad_trigger_button(0, 7, r); + last_r = r; + } + + float hat_x = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_HAT_X, 0); + + bool hat_left = false; + bool hat_right = false; + if (hat_x < -0.5f) { + hat_left = true; + } + else if (hat_x > 0.5f) { + hat_right = true; + } + + float hat_y = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_HAT_Y, 0); + + bool hat_up = false; + bool hat_down = false; + if (hat_y < -0.5f) { + hat_up = true; + } + else if (hat_y > 0.5f) { + hat_down = true; + } + + if (hat_left != last_hat_left) { + kinc_internal_gamepad_trigger_button(0, 14, hat_left ? 1.0f : 0.0f); + last_hat_left = hat_left; + } + + if (hat_right != last_hat_right) { + kinc_internal_gamepad_trigger_button(0, 15, hat_right ? 1.0f : 0.0f); + last_hat_right = hat_right; + } + + if (hat_up != last_hat_up) { + kinc_internal_gamepad_trigger_button(0, 12, hat_up ? 1.0f : 0.0f); + last_hat_up = hat_up; + } + + if (hat_down != last_hat_down) { + kinc_internal_gamepad_trigger_button(0, 13, hat_down ? 1.0f : 0.0f); + last_hat_down = hat_down; + } + return 1; } } @@ -171,7 +266,7 @@ namespace { return 1; case AKEYCODE_DPAD_CENTER: case AKEYCODE_BUTTON_B: - kinc_internal_gamepad_trigger_button(0, 0, 1); + kinc_internal_gamepad_trigger_button(0, 1, 1); return 1; case AKEYCODE_BACK: if (AKeyEvent_getMetaState(event) & AMETA_ALT_ON) { // Xperia Play @@ -183,13 +278,13 @@ namespace { return 1; } case AKEYCODE_BUTTON_A: - kinc_internal_gamepad_trigger_button(0, 1, 1); + kinc_internal_gamepad_trigger_button(0, 0, 1); return 1; case AKEYCODE_BUTTON_Y: - kinc_internal_gamepad_trigger_button(0, 2, 1); + kinc_internal_gamepad_trigger_button(0, 3, 1); return 1; case AKEYCODE_BUTTON_X: - kinc_internal_gamepad_trigger_button(0, 3, 1); + kinc_internal_gamepad_trigger_button(0, 2, 1); return 1; case AKEYCODE_BUTTON_L1: kinc_internal_gamepad_trigger_button(0, 4, 1); @@ -335,7 +430,7 @@ namespace { return 1; case AKEYCODE_DPAD_CENTER: case AKEYCODE_BUTTON_B: - kinc_internal_gamepad_trigger_button(0, 0, 0); + kinc_internal_gamepad_trigger_button(0, 1, 0); return 1; case AKEYCODE_BACK: if (AKeyEvent_getMetaState(event) & AMETA_ALT_ON) { // Xperia Play @@ -347,13 +442,13 @@ namespace { return 1; } case AKEYCODE_BUTTON_A: - kinc_internal_gamepad_trigger_button(0, 1, 0); + kinc_internal_gamepad_trigger_button(0, 0, 0); return 1; case AKEYCODE_BUTTON_Y: - kinc_internal_gamepad_trigger_button(0, 2, 0); + kinc_internal_gamepad_trigger_button(0, 3, 0); return 1; case AKEYCODE_BUTTON_X: - kinc_internal_gamepad_trigger_button(0, 3, 0); + kinc_internal_gamepad_trigger_button(0, 2, 0); return 1; case AKEYCODE_BUTTON_L1: kinc_internal_gamepad_trigger_button(0, 4, 0); @@ -547,6 +642,10 @@ namespace { } } } + + void resize(ANativeActivity *activity, ANativeWindow *window) { + activityJustResized = true; + } } ANativeActivity* KoreAndroid::getActivity() { @@ -621,14 +720,36 @@ const char* kinc_language() { return str; } +bool kinc_vulkan_internal_get_size(int *width, int *height); + int glWidth() { +#ifndef KORE_VULKAN glContext->UpdateSize(); return glContext->GetScreenWidth(); +#else + int width, height; + if (kinc_vulkan_internal_get_size(&width, &height)) { + return width; + } + else { + return ANativeWindow_getWidth(app->window); + } +#endif } int glHeight() { +#ifndef KORE_VULKAN glContext->UpdateSize(); return glContext->GetScreenHeight(); +#else + int width, height; + if (kinc_vulkan_internal_get_size(&width, &height)) { + return height; + } + else { + return ANativeWindow_getHeight(app->window); + } +#endif } const char* kinc_internal_save_path() { @@ -683,6 +804,8 @@ double kinc_time() { return (double)(now.tv_sec - start_sec) + (now.tv_usec / 1000000.0); } +extern "C" void kinc_internal_resize(int window, int width, int height); + bool kinc_internal_handle_messages(void) { int ident; int events; @@ -711,6 +834,16 @@ bool kinc_internal_handle_messages(void) { } } + if (activityJustResized && app->window != NULL) { + activityJustResized = false; + int32_t width = glWidth(); + int32_t height = glHeight(); +#ifdef KORE_VULKAN + kinc_internal_resize(0, width, height); +#endif + //kinc_internal_call_resize_callback(0, width, height); + } + if (app->destroyRequested != 0) { termDisplay(); kinc_stop(); @@ -778,8 +911,10 @@ extern "C" void android_main(android_app* app) { KoreAndroidVideoInit(); app->onAppCmd = cmd; app->onInputEvent = input; - + activity->callbacks->onNativeWindowResized = resize; +#ifndef KORE_VULKAN glContext = ndk_helper::GLContext::GetInstance(); +#endif sensorManager = ASensorManager_getInstance(); accelerometerSensor = ASensorManager_getDefaultSensor(sensorManager, ASENSOR_TYPE_ACCELEROMETER); gyroSensor = ASensorManager_getDefaultSensor(sensorManager, ASENSOR_TYPE_GYROSCOPE); @@ -833,3 +968,39 @@ extern "C" const char *kinc_gamepad_vendor(int gamepad) { extern "C" const char *kinc_gamepad_product_name(int gamepad) { return "gamepad"; } + +extern "C" bool kinc_internal_120hz(void) { + return false; +} + +extern "C" int kinc_count_dlcs(void) { + return 0; +} + +extern "C" const char *kinc_get_dlc(int index) { + return ""; +} + +extern "C" const char *kinc_language_ex() { + return "en_US"; +} + +extern "C" double kinc_local_time(void) { + return 0; +} + +extern "C" double kinc_hours(double time) { + return 0; +} + +extern "C" double kinc_minutes(double time) { + return 0; +} + +extern "C" double kinc_month(double time) { + return 0; +} + +extern "C" bool kinc_is_activity_start(void) { + return false; +} diff --git a/Backends/System/Android/Sources/Kore/Video.cpp b/Backends/System/Android/Sources/Kore/Video.cpp index eb5da29d6..82ab4c4aa 100644 --- a/Backends/System/Android/Sources/Kore/Video.cpp +++ b/Backends/System/Android/Sources/Kore/Video.cpp @@ -12,7 +12,7 @@ #include #include #include -#if KORE_ANDROID_API >= 15 +#if KORE_ANDROID_API >= 15 && !defined(KORE_VULKAN) #include #include #endif @@ -20,7 +20,7 @@ #include #include #include -#if KORE_ANDROID_API >= 15 +#if KORE_ANDROID_API >= 15 && !defined(KORE_VULKAN) #include #include #include @@ -40,7 +40,7 @@ bool VideoSoundStream::ended() { return false; } -#if KORE_ANDROID_API >= 15 +#if KORE_ANDROID_API >= 15 && !defined(KORE_VULKAN) namespace { const int videosCount = 10; @@ -434,7 +434,7 @@ namespace { #endif extern "C" JNIEXPORT void JNICALL Java_tech_kode_kore_KoreMoviePlayer_nativeCreate(JNIEnv* env, jobject jobj, jstring jpath, jobject surface, jint id) { -#if KORE_ANDROID_API >= 15 +#if KORE_ANDROID_API >= 15 && !defined(KORE_VULKAN) const char* path = env->GetStringUTFChars(jpath, NULL); AndroidVideo* av = new AndroidVideo; av->theNativeWindow = ANativeWindow_fromSurface(env, surface); @@ -467,7 +467,7 @@ void KoreAndroidVideoInit() { } Video::Video(const char* filename) : playing(false), sound(nullptr) { -#if KORE_ANDROID_API >= 15 +#if KORE_ANDROID_API >= 15 && !defined(KORE_VULKAN) Kore::log(Kore::Info, "Opening video %s.", filename); myWidth = 1023; myHeight = 684; @@ -504,7 +504,7 @@ Video::Video(const char* filename) : playing(false), sound(nullptr) { } Video::~Video() { -#if KORE_ANDROID_API >= 15 +#if KORE_ANDROID_API >= 15 && !defined(KORE_VULKAN) stop(); AndroidVideo* av = (AndroidVideo*)androidVideo; av->shutdown(); @@ -518,20 +518,20 @@ Video::~Video() { } void Video::play() { -#if KORE_ANDROID_API >= 15 +#if KORE_ANDROID_API >= 15 && !defined(KORE_VULKAN) playing = true; start = System::time(); #endif } void Video::pause() { -#if KORE_ANDROID_API >= 15 +#if KORE_ANDROID_API >= 15 && !defined(KORE_VULKAN) playing = false; #endif } void Video::stop() { -#if KORE_ANDROID_API >= 15 +#if KORE_ANDROID_API >= 15 && !defined(KORE_VULKAN) pause(); #endif } @@ -541,7 +541,7 @@ void Video::updateImage() {} void Video::update(double time) {} int Video::width() { -#if KORE_ANDROID_API >= 15 +#if KORE_ANDROID_API >= 15 && !defined(KORE_VULKAN) return myWidth; #else return 512; @@ -549,7 +549,7 @@ int Video::width() { } int Video::height() { -#if KORE_ANDROID_API >= 15 +#if KORE_ANDROID_API >= 15 && !defined(KORE_VULKAN) return myHeight; #else return 512; @@ -557,7 +557,7 @@ int Video::height() { } Graphics4::Texture* Video::currentImage() { -#if KORE_ANDROID_API >= 15 +#if KORE_ANDROID_API >= 15 && !defined(KORE_VULKAN) return image; #else return nullptr; diff --git a/Backends/System/POSIX/Sources/Kore/AtomicImpl.h b/Backends/System/POSIX/Sources/Kore/AtomicImpl.h index 10569ab64..56d3b7ee7 100644 --- a/Backends/System/POSIX/Sources/Kore/AtomicImpl.h +++ b/Backends/System/POSIX/Sources/Kore/AtomicImpl.h @@ -16,12 +16,16 @@ // clang/gcc intrinsics -#define KINC_ATOMIC_COMPARE_EXCHANGE(pointer, oldValue, newValue) (__sync_bool_compare_and_swap(pointer, oldValue, newValue)) +#define KINC_ATOMIC_COMPARE_EXCHANGE(pointer, oldValue, newValue) (__sync_val_compare_and_swap(pointer, oldValue, newValue) == oldValue) -#define KINC_ATOMIC_COMPARE_EXCHANGE_POINTER(pointer, oldValue, newValue) (__sync_bool_compare_and_swap(pointer, oldValue, newValue)) +#define KINC_ATOMIC_COMPARE_EXCHANGE_POINTER(pointer, oldValue, newValue) (__sync_val_compare_and_swap(pointer, oldValue, newValue) == oldValue) #define KINC_ATOMIC_INCREMENT(pointer) (__sync_fetch_and_add(pointer, 1)) #define KINC_ATOMIC_DECREMENT(pointer) (__sync_fetch_and_sub(pointer, 1)) +#define KINC_ATOMIC_EXCHANGE_32(pointer, value) (__sync_swap(pointer, value)) + +#define KINC_ATOMIC_EXCHANGE_FLOAT(pointer, value) (__sync_swap((volatile int32_t *)pointer, *(int32_t *)&value)) + #endif diff --git a/Backends/System/Windows/Sources/Kore/Display.c b/Backends/System/Windows/Sources/Kore/Display.c index ffd8882cb..4f489cdc6 100644 --- a/Backends/System/Windows/Sources/Kore/Display.c +++ b/Backends/System/Windows/Sources/Kore/Display.c @@ -3,8 +3,8 @@ #include #include -#include #include +#include #include @@ -35,8 +35,8 @@ static BOOL CALLBACK EnumerationCallback(HMONITOR monitor, HDC hdc_unused, LPREC MONITORINFOEXA info; memset(&info, 0, sizeof(MONITORINFOEXA)); info.cbSize = sizeof(MONITORINFOEXA); - - if (GetMonitorInfoA(monitor, (MONITORINFO*)&info) == FALSE) { + + if (GetMonitorInfoA(monitor, (MONITORINFO *)&info) == FALSE) { return FALSE; } @@ -61,7 +61,7 @@ static BOOL CALLBACK EnumerationCallback(HMONITOR monitor, HDC hdc_unused, LPREC display->y = info.rcMonitor.top; display->width = info.rcMonitor.right - info.rcMonitor.left; display->height = info.rcMonitor.bottom - info.rcMonitor.top; - + HDC hdc = CreateDCA(NULL, display->name, NULL, NULL); display->ppi = GetDeviceCaps(hdc, LOGPIXELSX); int scale = GetDeviceCaps(hdc, SCALINGFACTORX); @@ -149,13 +149,13 @@ bool kinc_windows_set_display_mode(int display_index, int width, int height, int display->mode_changed = true; DEVMODEA mode = {0}; mode.dmSize = sizeof(mode); - strcpy((char*)mode.dmDeviceName, display->name); + strcpy((char *)mode.dmDeviceName, display->name); mode.dmPelsWidth = width; mode.dmPelsHeight = height; mode.dmBitsPerPel = bpp; mode.dmDisplayFrequency = frequency; mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY; - + return ChangeDisplaySettingsA(&mode, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL; } @@ -167,7 +167,7 @@ void kinc_windows_restore_display(int display) { void kinc_windows_restore_displays() { for (int i = 0; i < MAXIMUM_DISPLAYS; ++i) { - kinc_windows_restore_display(i); + kinc_windows_restore_display(i); } } @@ -194,3 +194,7 @@ kinc_display_mode_t kinc_display_current_mode(int display_index) { mode.bits_per_pixel = display->bpp; return mode; } + +bool kinc_internal_120hz(void) { + return kinc_display_current_mode(kinc_primary_display()).frequency == 120; +} diff --git a/Backends/System/Windows/Sources/Kore/System.cpp b/Backends/System/Windows/Sources/Kore/System.cpp index 11a4f8851..b00033c2d 100644 --- a/Backends/System/Windows/Sources/Kore/System.cpp +++ b/Backends/System/Windows/Sources/Kore/System.cpp @@ -980,6 +980,8 @@ bool kinc_internal_handle_messages() { namespace { bool keyboardshown = false; + char language[3] = {0}; + char language_ex[6] = {0}; } void kinc_keyboard_show() { @@ -1000,18 +1002,51 @@ void kinc_set_keep_screen_on(bool on) {} void kinc_vibrate(int ms) {} const char *kinc_language() { + wchar_t wlanguage[3] = {0}; + + if (GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SISO639LANGNAME, wlanguage, 3)) { + WideCharToMultiByte(CP_UTF8, 0, wlanguage, -1, language, 3, nullptr, nullptr); + return language; + } return "en"; } +const char *kinc_language_ex() { + wchar_t wlanguage[3] = {0}; + wchar_t wcountry[3] = {0}; + char language[3] = {0}; + char country[3] = {0}; + + if (GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SISO639LANGNAME, wlanguage, 3) && + GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SISO3166CTRYNAME, wcountry, 3)) { + WideCharToMultiByte(CP_UTF8, 0, wlanguage, -1, language, 3, nullptr, nullptr); + WideCharToMultiByte(CP_UTF8, 0, wcountry, -1, country, 3, nullptr, nullptr); + strcpy(language_ex, language); + strcat(language_ex, "_"); + strcat(language_ex, country); + return language_ex; + } + return "en_US"; +} + const char *kinc_system_id() { return "Windows"; } namespace { +#if !defined(KINC_SAVE_IN_DOCUMENTS) wchar_t savePathw[2048] = {0}; +#endif char savePath[2048] = {0}; void findSavePath() { +#if defined(KINC_SAVE_IN_DOCUMENTS) + strcpy(savePath, getenv("USERPROFILE")); + strcat(savePath, "\\Documents\\"); + strcat(savePath, kinc_application_name()); + strcat(savePath, "\\"); + SHCreateDirectoryExA(nullptr, savePath, nullptr); +#else CoInitialize(NULL); IKnownFolderManager *folders = nullptr; CoCreateInstance(CLSID_KnownFolderManager, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&folders)); @@ -1034,7 +1069,8 @@ namespace { CoTaskMemFree(path); folder->Release(); folders->Release(); - // CoUninitialize(); +// CoUninitialize(); +#endif } } @@ -1077,6 +1113,18 @@ double kinc_time(void) { return double(stamp.QuadPart - startCount.QuadPart) / (double)::frequency.QuadPart; } +extern "C" int kinc_count_dlcs(void) { + return 0; +} + +extern "C" const char *kinc_get_dlc(int index) { + return ""; +} + +extern "C" bool kinc_is_activity_start(void) { + return false; +} + int WINAPI WinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPSTR lpCmdLine, int /*nCmdShow*/) { // Pen functions are only in Windows 8 and later, so load them dynamically HMODULE user32 = LoadLibraryA("user32.dll"); diff --git a/Backends/System/Windows/Sources/Kore/Window.c b/Backends/System/Windows/Sources/Kore/Window.c index d603129df..181fe38ee 100644 --- a/Backends/System/Windows/Sources/Kore/Window.c +++ b/Backends/System/Windows/Sources/Kore/Window.c @@ -44,6 +44,20 @@ static int window_counter = 0; const wchar_t *windowClassName = L"KoreWindow"; #endif +#ifdef KORE_VULKAN +#include + + VkResult kinc_vulkan_create_surface(VkInstance instance, int window_index, VkSurfaceKHR *surface) { + VkWin32SurfaceCreateInfoKHR createInfo = {0}; + createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; + createInfo.pNext = NULL; + createInfo.flags = 0; + createInfo.hinstance = GetModuleHandle(NULL); + createInfo.hwnd = windows[window_index].handle; + return vkCreateWin32SurfaceKHR(instance, &createInfo, NULL, surface); + } +#endif + static void RegisterWindowClass(HINSTANCE hInstance, const wchar_t *className) { WNDCLASSEXW wc = {sizeof(WNDCLASSEXA), CS_OWNDC /*CS_CLASSDC*/, diff --git a/Sources/Kore/Graphics1/Image.cpp b/Sources/Kore/Graphics1/Image.cpp index cb3d927af..bde484389 100644 --- a/Sources/Kore/Graphics1/Image.cpp +++ b/Sources/Kore/Graphics1/Image.cpp @@ -1,9 +1,5 @@ #include "pch.h" -#if defined(KORE_WINDOWS) && defined(KORE_VULKAN) -#include -#endif - #include "Image.h" #include diff --git a/Sources/Kore/System.cpp b/Sources/Kore/System.cpp index 6769924a5..48ac0cc8d 100644 --- a/Sources/Kore/System.cpp +++ b/Sources/Kore/System.cpp @@ -215,6 +215,21 @@ const char* Kore::System::language() { return kinc_language(); } +const char *Kore::System::languageEx() { + return kinc_language_ex(); +} + +extern "C" int kinc_count_dlcs(void); +extern "C" const char *kinc_get_dlc(int index); + +int Kore::System::dlcCount() { + return kinc_count_dlcs(); +} + +const char *Kore::System::dlc(int index) { + return kinc_get_dlc(index); +} + void Kore::System::showKeyboard() { kinc_keyboard_show(); } diff --git a/Sources/Kore/System.h b/Sources/Kore/System.h index c2a54e23c..06f91a2fd 100644 --- a/Sources/Kore/System.h +++ b/Sources/Kore/System.h @@ -20,6 +20,9 @@ namespace Kore { bool showsKeyboard(); void loadURL(const char* title); const char* language(); + const char *languageEx(); + int dlcCount(); + const char *dlc(int index); void vibrate(int ms); const char* systemId(); const char* savePath(); diff --git a/Sources/Kore/Threads/Mutex.h b/Sources/Kore/Threads/Mutex.h index 060b498ba..f143ed2a2 100644 --- a/Sources/Kore/Threads/Mutex.h +++ b/Sources/Kore/Threads/Mutex.h @@ -17,7 +17,7 @@ namespace Kore { void unlock(); private: -#if defined(KORE_WINDOWS) || defined(KORE_WINDOWSAPP) || defined(KORE_XBOX_ONE) +#if defined(KORE_WINDOWS) || defined(KORE_WINDOWSAPP) || defined(KORE_XBOX_ONE) || defined(KORE_XBOX_SCARLETT) struct CriticalSection { void* DebugInfo; long LockCount; diff --git a/Sources/kinc/io/filereader.h b/Sources/kinc/io/filereader.h index 9aca5ec90..ac1700567 100644 --- a/Sources/kinc/io/filereader.h +++ b/Sources/kinc/io/filereader.h @@ -1,6 +1,6 @@ #pragma once -#if defined(KORE_SONY) || defined(KORE_SWITCH) +#if defined(KORE_SONY) || defined(KORE_SWITCH) || defined(KORE_SWITCH2) #include #endif @@ -40,7 +40,7 @@ typedef struct kinc_file_reader { int type; int mode; bool mounted; -#if defined(KORE_SONY) || defined(KORE_SWITCH) +#if defined(KORE_SONY) || defined(KORE_SWITCH) || defined(KORE_SWITCH2) kinc_file_reader_impl_t impl; #endif } kinc_file_reader_t; diff --git a/Sources/kinc/io/filewriter.c b/Sources/kinc/io/filewriter.c index f9c49ac37..ef3c7aba6 100644 --- a/Sources/kinc/io/filewriter.c +++ b/Sources/kinc/io/filewriter.c @@ -11,7 +11,7 @@ #include #include -#if defined(KORE_PS4) || defined(KORE_SWITCH) +#if defined(KORE_PS4) || defined(KORE_SWITCH) || defined(KORE_SWITCH2) #define MOUNT_SAVES bool mountSaveData(bool); void unmountSaveData(); diff --git a/Sources/kinc/simd/float32x4.h b/Sources/kinc/simd/float32x4.h index 888458aa6..8d35a1162 100644 --- a/Sources/kinc/simd/float32x4.h +++ b/Sources/kinc/simd/float32x4.h @@ -65,7 +65,7 @@ inline kinc_float32x4_t kinc_float32x4_sqrt(kinc_float32x4_t t) { return _mm_sqrt_ps(t); } -#elif defined(KORE_IOS) || defined(KORE_SWITCH) +#elif defined(KORE_IOS) || defined(KORE_SWITCH) || defined(KORE_SWITCH2) #include @@ -92,7 +92,7 @@ inline kinc_float32x4_t kinc_float32x4_add(kinc_float32x4_t a, kinc_float32x4_t } inline kinc_float32x4_t kinc_float32x4_div(kinc_float32x4_t a, kinc_float32x4_t b) { -#if defined(ARM64) || defined(KORE_SWITCH) +#if defined(ARM64) || defined(KORE_SWITCH) || defined(KORE_SWITCH2) return vdivq_f32(a, b); #else float32x4_t inv = vrecpeq_f32(b); @@ -123,7 +123,7 @@ inline kinc_float32x4_t kinc_float32x4_sub(kinc_float32x4_t a, kinc_float32x4_t } inline kinc_float32x4_t kinc_float32x4_sqrt(kinc_float32x4_t t) { -#if defined(ARM64) || defined(KORE_SWITCH) +#if defined(ARM64) || defined(KORE_SWITCH) || defined(KORE_SWITCH2) return vsqrtq_f32(t); #else return vmulq_f32(t, vrsqrteq_f32(t)); diff --git a/Sources/kinc/system.c b/Sources/kinc/system.c index 375d70c78..35541a87c 100644 --- a/Sources/kinc/system.c +++ b/Sources/kinc/system.c @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -194,7 +195,7 @@ bool kinc_internal_frame() { void kinc_start() { running = true; -#if !defined(KORE_HTML5) && !defined(KORE_TIZEN) && !defined(KORE_XBOX_ONE) +#if !defined(KORE_HTML5) && !defined(KORE_TIZEN) // if (Graphics::hasWindow()) Graphics::swapBuffers(); #if defined(KORE_IOS) || defined(KORE_MACOS) @@ -220,15 +221,23 @@ int kinc_height() { void kinc_memory_emergency() {} #endif -#if !defined(KORE_SONY) && !defined(KORE_SWITCH) +#if !defined(KORE_SONY) && !defined(KORE_SWITCH) && !defined(KORE_SWITCH2) static float safe_zone = 0.9f; float kinc_safe_zone(void) { +#ifdef KORE_ANDROID + return 1.0f; +#else return safe_zone; +#endif } bool kinc_automatic_safe_zone() { +#ifdef KORE_ANDROID + return true; +#else return false; +#endif } void kinc_set_safe_zone(float value) { @@ -290,11 +299,18 @@ void kinc_load_save_file(const char *filename) { } } +static void commit_save(const char *old_filename, const char *new_filename); + void kinc_save_save_file(const char *filename, uint8_t *data, size_t size) { + char temp_filename[1001]; + strcpy(temp_filename, filename); + strcat(temp_filename, ".kinctemp"); + kinc_file_writer_t writer; - if (kinc_file_writer_open(&writer, filename)) { + if (kinc_file_writer_open(&writer, temp_filename)) { kinc_file_writer_write(&writer, data, (int)size); kinc_file_writer_close(&writer); + commit_save(temp_filename, filename); } } @@ -307,3 +323,79 @@ bool kinc_waiting_for_login() { } #endif + +#ifdef KORE_WINDOWS +#include + +static void commit_save(const char *old_filename, const char *new_filename) { + char old_path[1001]; + strcpy(old_path, kinc_internal_save_path()); + strcat(old_path, old_filename); + + char new_path[1001]; + strcpy(new_path, kinc_internal_save_path()); + strcat(new_path, new_filename); + + if (!MoveFileExA(old_path, new_path, MOVEFILE_REPLACE_EXISTING)) { + kinc_log(KINC_LOG_LEVEL_WARNING, "Could not save (error code %d)", GetLastError()); + } +} + +double kinc_local_time() { + SYSTEMTIME system_time; + GetLocalTime(&system_time); + FILETIME file_time; + SystemTimeToFileTime(&system_time, &file_time); + ULARGE_INTEGER large_time; + large_time.LowPart = file_time.dwLowDateTime; + large_time.HighPart = file_time.dwHighDateTime; + unsigned long long time = large_time.QuadPart; + time /= 10; + return (double)time; +} + +double kinc_hours(double time) { + unsigned long long utime = (unsigned long long)time; + utime *= 10; + ULARGE_INTEGER large_time; + large_time.QuadPart = utime; + FILETIME file_time; + file_time.dwLowDateTime = large_time.LowPart; + file_time.dwHighDateTime = large_time.HighPart; + SYSTEMTIME system_time; + FileTimeToSystemTime(&file_time, &system_time); + return (double)system_time.wHour; +} + +double kinc_minutes(double time) { + unsigned long long utime = (unsigned long long)time; + utime *= 10; + ULARGE_INTEGER large_time; + large_time.QuadPart = utime; + FILETIME file_time; + file_time.dwLowDateTime = large_time.LowPart; + file_time.dwHighDateTime = large_time.HighPart; + SYSTEMTIME system_time; + FileTimeToSystemTime(&file_time, &system_time); + return (double)system_time.wMinute; +} + +double kinc_month(double time) { + unsigned long long utime = (unsigned long long)time; + utime *= 10; + ULARGE_INTEGER large_time; + large_time.QuadPart = utime; + FILETIME file_time; + file_time.dwLowDateTime = large_time.LowPart; + file_time.dwHighDateTime = large_time.HighPart; + SYSTEMTIME system_time; + FileTimeToSystemTime(&file_time, &system_time); + return (double)(system_time.wMonth - 1); +} +#endif + +#ifdef KORE_ANDROID +static void commit_save(const char *old_filename, const char *new_filename) { + +} +#endif diff --git a/Sources/kinc/system.h b/Sources/kinc/system.h index 647acdb71..71578a1d0 100644 --- a/Sources/kinc/system.h +++ b/Sources/kinc/system.h @@ -30,6 +30,8 @@ const char **kinc_video_formats(); const char *kinc_language(); +const char *kinc_language_ex(); + void kinc_vibrate(int milliseconds); float kinc_safe_zone(); diff --git a/Tools/kincmake b/Tools/kincmake index 6abc7153a..5c21ac051 160000 --- a/Tools/kincmake +++ b/Tools/kincmake @@ -1 +1 @@ -Subproject commit 6abc7153a75b9cfd194f239b46098618f9c7dcad +Subproject commit 5c21ac051e4ffd53044d8a49d4b50a8c20b0d52f diff --git a/Tools/krafix b/Tools/krafix index b61ae801f..d692b8490 160000 --- a/Tools/krafix +++ b/Tools/krafix @@ -1 +1 @@ -Subproject commit b61ae801f2b8d3f1b840558df7d6f82613a81295 +Subproject commit d692b8490420f67453960693ba0b7113c664e48c diff --git a/kincfile.js b/kincfile.js index e4c0dca60..fba3f573a 100644 --- a/kincfile.js +++ b/kincfile.js @@ -34,7 +34,7 @@ if (lz4x) { project.addExclude('Sources/kinc/io/lz4/**'); } else { - project.addExclude('Sources/kinc/libs/lz4x.cpp'); + project.addExclude('Sources/kinc/libs/lz4x.cpp'); } project.addIncludeDir('Sources'); @@ -102,14 +102,7 @@ if (platform === Platform.Windows) { addBackend('Graphics5/Vulkan'); project.addDefine('KORE_VULKAN'); project.addDefine('VK_USE_PLATFORM_WIN32_KHR'); - project.addLibFor('Win32', path.join(process.env.VULKAN_SDK, 'Lib32', 'vulkan-1')); project.addLibFor('x64', path.join(process.env.VULKAN_SDK, 'Lib', 'vulkan-1')); - let libs = fs.readdirSync(path.join(process.env.VULKAN_SDK, 'Lib32')); - for (const lib of libs) { - if (lib.startsWith('VkLayer_')) { - project.addLibFor('Win32', path.join(process.env.VULKAN_SDK, 'Lib32', lib.substr(0, lib.length - 4))); - } - } libs = fs.readdirSync(path.join(process.env.VULKAN_SDK, 'Lib')); for (const lib of libs) { if (lib.startsWith('VkLayer_')) { @@ -117,6 +110,10 @@ if (platform === Platform.Windows) { } } project.addIncludeDir(path.join(process.env.VULKAN_SDK, 'Include')); + if (raytrace === RayTraceApi.VKRT) { + project.addDefine('KORE_VKRT'); + project.addDefine('VK_ENABLE_BETA_EXTENSIONS'); + } } else if (graphics === GraphicsApi.Direct3D9) { g4 = true; @@ -176,7 +173,7 @@ else if (platform === Platform.WindowsApp) { addBackend('Audio2/WASAPI'); project.addDefine('_CRT_SECURE_NO_WARNINGS'); project.vsdeploy = true; - + if (vr === VrApi.Hololens) { project.addDefine('KORE_VR'); project.addDefine('KORE_HOLOLENS'); @@ -275,17 +272,20 @@ else if (platform === Platform.Android) { g5 = true; addBackend('Graphics5/Vulkan'); project.addDefine('KORE_VULKAN'); + project.addDefine('VK_USE_PLATFORM_ANDROID_KHR'); + project.addLib("vulkan"); + project.addDefine('KORE_ANDROID_API=24'); } else if (graphics === GraphicsApi.OpenGL || graphics === GraphicsApi.Default) { g4 = true; addBackend('Graphics4/OpenGL'); project.addDefine('KORE_OPENGL'); project.addDefine('KORE_OPENGL_ES'); + project.addDefine('KORE_ANDROID_API=15'); } else { throw new Error('Graphics API ' + graphics + ' is not available for Android.'); } - project.addDefine('KORE_ANDROID_API=15'); project.addDefine('KORE_POSIX'); project.addLib('log'); project.addLib('android'); @@ -328,6 +328,10 @@ else if (platform === Platform.Linux) { project.addLib('xcb'); project.addDefine('KORE_VULKAN'); project.addDefine('VK_USE_PLATFORM_XCB_KHR'); + if (raytrace === RayTraceApi.VKRT) { + project.addDefine('KORE_VKRT'); + project.addDefine('VK_ENABLE_BETA_EXTENSIONS'); + } } else if (graphics === GraphicsApi.OpenGL || graphics === GraphicsApi.Default) { g4 = true; @@ -361,7 +365,7 @@ else if (platform === Platform.Pi) { project.addLib('EGL'); project.addLib('bcm_host'); project.addLib('asound'); - project.addLib('X11'); + project.addLib('X11'); } else if (platform === Platform.Tizen) { g4 = true; @@ -415,6 +419,9 @@ if (plugin) { else if (platform === Platform.Switch) { backend = 'Switch'; } + else if (platform === Platform.Switch2) { + backend = 'Switch2'; + } else if (platform === Platform.XboxScarlett) { backend = 'XboxScarlett'; }