mirror of
https://github.com/Inori/GPCS4.git
synced 2024-06-02 19:38:19 -04:00
create vlt device in gnm driver
This commit is contained in:
parent
a4265a22a9
commit
760068a2b8
|
@ -26,7 +26,7 @@ ColumnLimit: 0
|
|||
SortIncludes: true
|
||||
IncludeBlocks: Regroup
|
||||
IncludeCategories:
|
||||
- Regex: '^"(\.\.|Platform|Emulator|Graphic|Loader|Algorithm|Util)/'
|
||||
- Regex: '^"(\.\.|Platform|Emulator|Graphic|Loader|Algorithm|Util|Sce|Gnm|Pssl|SpirV|Violet|SceModules)/'
|
||||
Priority: 2
|
||||
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
||||
Priority: 3
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#include <spdlog/sinks/stdout_color_sinks.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
#define LOG_STR_BUFFER_LEN 2000
|
||||
#define LOG_STR_BUFFER_LEN 0x2000
|
||||
|
||||
#ifdef GPCS4_WINDOWS
|
||||
|
||||
|
|
|
@ -119,6 +119,7 @@
|
|||
<ClInclude Include="Platform\PlatString.h" />
|
||||
<ClInclude Include="Platform\PlatThread.h" />
|
||||
<ClInclude Include="Platform\PlatTime.h" />
|
||||
<ClInclude Include="Platform\PlatVulkan.h" />
|
||||
<ClInclude Include="SceModules\BlockingQueue.h" />
|
||||
<ClInclude Include="SceModules\MapSlot.h" />
|
||||
<ClInclude Include="SceModules\SceAjm\sce_ajm.h" />
|
||||
|
@ -276,6 +277,7 @@
|
|||
<ClCompile Include="Platform\PlatString.cpp" />
|
||||
<ClCompile Include="Platform\PlatThread.cpp" />
|
||||
<ClCompile Include="Platform\PlatTime.cpp" />
|
||||
<ClCompile Include="Platform\PlatVulkan.cpp" />
|
||||
<ClCompile Include="SceModules\SceAjm\sce_ajm.cpp" />
|
||||
<ClCompile Include="SceModules\SceAjm\sce_ajm_export.cpp" />
|
||||
<ClCompile Include="SceModules\SceAppContentUtil\sce_appcontentutil.cpp" />
|
||||
|
|
|
@ -733,6 +733,9 @@
|
|||
<ClInclude Include="Graphics\Violet\VltRecycler.h">
|
||||
<Filter>Source Files\Graphics\Violet</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Platform\PlatVulkan.h">
|
||||
<Filter>Source Files\Platform</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Loader\EbootObject.cpp">
|
||||
|
@ -1263,6 +1266,9 @@
|
|||
<ClCompile Include="Graphics\Violet\VltDevice.cpp">
|
||||
<Filter>Source Files\Graphics\Violet</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Platform\PlatVulkan.cpp">
|
||||
<Filter>Source Files\Platform</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="Emulator\TLSStub.asm">
|
||||
|
|
|
@ -4,9 +4,13 @@
|
|||
#include "UtilMath.h"
|
||||
#include "sce_errors.h"
|
||||
|
||||
#include "Gnm/GnmCommandProcessor.h"
|
||||
#include "Gnm/GnmCommandBufferDraw.h"
|
||||
#include "Gnm/GnmCommandBufferDummy.h"
|
||||
#include "Gnm/GnmCommandProcessor.h"
|
||||
#include "Violet/VltAdapter.h"
|
||||
#include "Violet/VltDevice.h"
|
||||
#include "Violet/VltInstance.h"
|
||||
|
||||
|
||||
LOG_CHANNEL(Graphic.Sce.SceGnmDriver);
|
||||
|
||||
|
@ -14,205 +18,238 @@ extern "C" void glfwPollEvents(void);
|
|||
|
||||
namespace sce
|
||||
{
|
||||
using namespace vlt;
|
||||
|
||||
SceGnmDriver::SceGnmDriver()
|
||||
{
|
||||
bool success = initGnmDriver();
|
||||
LOG_ASSERT(success == true, "init Gnm Driver failed.");
|
||||
}
|
||||
|
||||
SceGnmDriver::~SceGnmDriver()
|
||||
{
|
||||
// TODO:
|
||||
// Correct the reference count maintenance, thus we don't
|
||||
// need to handle release order manually.
|
||||
// e.g. wrap VkSurfaceKHR in a class with reference count
|
||||
|
||||
m_graphicsQueue.reset();
|
||||
// Release Presenter before VideoOut
|
||||
// m_presenter = nullptr;
|
||||
}
|
||||
|
||||
bool SceGnmDriver::initGnmDriver()
|
||||
{
|
||||
bool ret = false;
|
||||
do
|
||||
SceGnmDriver::SceGnmDriver()
|
||||
{
|
||||
// A GPU must have a graphics queue by default.
|
||||
createGraphicsQueue();
|
||||
ret = true;
|
||||
} while (false);
|
||||
return ret;
|
||||
}
|
||||
bool success = initGnmDriver();
|
||||
LOG_ASSERT(success == true, "init Gnm Driver failed.");
|
||||
}
|
||||
|
||||
int SceGnmDriver::submitCommandBuffers(uint32_t count,
|
||||
void* dcbGpuAddrs[],
|
||||
uint32_t* dcbSizesInBytes,
|
||||
void* ccbGpuAddrs[],
|
||||
uint32_t* ccbSizesInBytes)
|
||||
{
|
||||
return submitAndFlipCommandBuffers(count,
|
||||
dcbGpuAddrs, dcbSizesInBytes,
|
||||
ccbGpuAddrs, ccbSizesInBytes,
|
||||
0, 0, 0, 0);
|
||||
}
|
||||
|
||||
int SceGnmDriver::submitAndFlipCommandBuffers(uint32_t count,
|
||||
void* dcbGpuAddrs[],
|
||||
uint32_t* dcbSizesInBytes,
|
||||
void* ccbGpuAddrs[],
|
||||
uint32_t* ccbSizesInBytes,
|
||||
uint32_t videoOutHandle,
|
||||
uint32_t displayBufferIndex,
|
||||
uint32_t flipMode,
|
||||
int64_t flipArg)
|
||||
{
|
||||
// There's only one hardware graphics queue for most of modern GPUs, including the one on PS4.
|
||||
// Thus a PS4 game will call submit function to submit command buffers sequentially,
|
||||
// and normally in one same thread.
|
||||
// We just emulate the GPU, parsing and executing one command buffer per call.
|
||||
|
||||
// TODO:
|
||||
// For real PS4 system, the submit call is asynchronous.
|
||||
// Thus for future development, we should record vulkan command buffer asynchronously too,
|
||||
// reducing time period of the submit call.
|
||||
|
||||
LOG_ASSERT(count == 1, "Currently only support 1 cmdbuff at one call.");
|
||||
|
||||
SceGpuCommand cmd = {};
|
||||
cmd.buffer = dcbGpuAddrs[0];
|
||||
cmd.size = dcbSizesInBytes[0];
|
||||
m_graphicsQueue->record(cmd);
|
||||
|
||||
submitPresent();
|
||||
|
||||
return SCE_OK;
|
||||
}
|
||||
|
||||
void SceGnmDriver::submitPresent()
|
||||
{
|
||||
do
|
||||
SceGnmDriver::~SceGnmDriver()
|
||||
{
|
||||
//if (!cmdList)
|
||||
//{
|
||||
// break;
|
||||
//}
|
||||
// TODO:
|
||||
// Correct the reference count maintenance, thus we don't
|
||||
// need to handle release order manually.
|
||||
// e.g. wrap VkSurfaceKHR in a class with reference count
|
||||
|
||||
SceGpuSubmission gpuSubmission = {};
|
||||
//gpuSubmission.cmdList = cmdList;
|
||||
//gpuSubmission.wait = presentSync.acquire;
|
||||
//gpuSubmission.wake = presentSync.present;
|
||||
m_graphicsQueue->submit(gpuSubmission);
|
||||
m_graphicsQueue.reset();
|
||||
// Release Presenter before VideoOut
|
||||
// m_presenter = nullptr;
|
||||
}
|
||||
|
||||
//VltPresentInfo presentation;
|
||||
//presentation.presenter = m_presenter;
|
||||
//presentation.waitSync = gpuSubmission.wake;
|
||||
//m_device->presentImage(presentation);
|
||||
|
||||
} while (false);
|
||||
}
|
||||
|
||||
int SceGnmDriver::sceGnmSubmitDone(void)
|
||||
{
|
||||
// Gnm::submitDone() is the place to hint the PS4 OS that
|
||||
// all the currently running GPU tasks (graphics and compute) are done for a frame,
|
||||
// such that the OS get the permission to do some extra stuffs.
|
||||
//
|
||||
// Since we use a window to emulate the hardware display, we need a place
|
||||
// to process the window event.
|
||||
// Currently I didn't find a very good place, so I place it here.
|
||||
glfwPollEvents();
|
||||
return SCE_OK;
|
||||
}
|
||||
|
||||
void SceGnmDriver::createGraphicsQueue()
|
||||
{
|
||||
// Create the only graphics queue.
|
||||
SceGpuQueueDevice gfxDevice = {};
|
||||
m_graphicsQueue = std::make_unique<SceGpuQueue>(gfxDevice, SceQueueType::Graphics);
|
||||
}
|
||||
|
||||
uint32_t SceGnmDriver::mapComputeQueue(uint32_t pipeId,
|
||||
uint32_t queueId,
|
||||
void* ringBaseAddr,
|
||||
uint32_t ringSizeInDW,
|
||||
void* readPtrAddr)
|
||||
{
|
||||
int vqueueId = SCE_GNM_ERROR_UNKNOWN;
|
||||
do
|
||||
bool SceGnmDriver::initGnmDriver()
|
||||
{
|
||||
if (pipeId >= MaxPipeId)
|
||||
bool ret = false;
|
||||
do
|
||||
{
|
||||
vqueueId = SCE_GNM_ERROR_COMPUTEQUEUE_INVALID_PIPE_ID;
|
||||
break;
|
||||
}
|
||||
if (!initVltDevice())
|
||||
{
|
||||
LOG_ERR("init vlt device failed.");
|
||||
break;
|
||||
}
|
||||
|
||||
if (queueId >= MaxQueueId)
|
||||
{
|
||||
vqueueId = SCE_GNM_ERROR_COMPUTEQUEUE_INVALID_QUEUE_ID;
|
||||
break;
|
||||
}
|
||||
// A GPU must have a graphics queue by default.
|
||||
createGraphicsQueue();
|
||||
ret = true;
|
||||
} while (false);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((uintptr_t)ringBaseAddr % 256 != 0)
|
||||
{
|
||||
vqueueId = SCE_GNM_ERROR_COMPUTEQUEUE_INVALID_RING_BASE_ADDR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!::util::isPowerOfTwo(ringSizeInDW))
|
||||
{
|
||||
vqueueId = SCE_GNM_ERROR_COMPUTEQUEUE_INVALID_RING_SIZE;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((uintptr_t)readPtrAddr % 4 != 0)
|
||||
{
|
||||
vqueueId = SCE_GNM_ERROR_COMPUTEQUEUE_INVALID_READ_PTR_ADDR;
|
||||
break;
|
||||
}
|
||||
|
||||
*(uint32_t*)readPtrAddr = 0;
|
||||
|
||||
vqueueId = VQueueIdBegin + pipeId * MaxPipeId + queueId;
|
||||
if (vqueueId >= MaxComputeQueueCount)
|
||||
{
|
||||
LOG_ERR("vqueueId is larger than max queue count.");
|
||||
break;
|
||||
}
|
||||
|
||||
SceGpuQueueDevice cptDevice = {};
|
||||
//cptDevice.device = m_device;
|
||||
//cptDevice.presenter = nullptr;
|
||||
//cptDevice.videoOut = nullptr;
|
||||
|
||||
uint32_t vqueueIndex = vqueueId - VQueueIdBegin;
|
||||
m_computeQueues[vqueueIndex] = std::make_unique<SceGpuQueue>(cptDevice, SceQueueType::Compute);
|
||||
|
||||
} while (false);
|
||||
|
||||
return vqueueId;
|
||||
}
|
||||
|
||||
void SceGnmDriver::unmapComputeQueue(uint32_t vqueueId)
|
||||
{
|
||||
do
|
||||
bool SceGnmDriver::initVltDevice()
|
||||
{
|
||||
if (vqueueId >= MaxComputeQueueCount)
|
||||
bool ret = false;
|
||||
do
|
||||
{
|
||||
LOG_ERR("vqueueId is larger than max queue count.");
|
||||
break;
|
||||
}
|
||||
m_instance = new VltInstance();
|
||||
|
||||
uint32_t vqueueIndex = vqueueId - VQueueIdBegin;
|
||||
m_computeQueues[vqueueIndex].reset();
|
||||
// adapters are ranked internally by their power
|
||||
// typically first one is the most powerful GPU in system
|
||||
m_adapter = m_instance->enumAdapters(0);
|
||||
if (!m_adapter)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
} while (false);
|
||||
}
|
||||
m_device = m_adapter->createDevice(m_instance);
|
||||
if (!m_device)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
void SceGnmDriver::dingDong(
|
||||
uint32_t vqueueId,
|
||||
uint32_t nextStartOffsetInDw)
|
||||
{
|
||||
}
|
||||
ret = true;
|
||||
}while(false);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SceGnmDriver::submitCommandBuffers(uint32_t count,
|
||||
void* dcbGpuAddrs[],
|
||||
uint32_t* dcbSizesInBytes,
|
||||
void* ccbGpuAddrs[],
|
||||
uint32_t* ccbSizesInBytes)
|
||||
{
|
||||
return submitAndFlipCommandBuffers(count,
|
||||
dcbGpuAddrs, dcbSizesInBytes,
|
||||
ccbGpuAddrs, ccbSizesInBytes,
|
||||
0, 0, 0, 0);
|
||||
}
|
||||
|
||||
int SceGnmDriver::submitAndFlipCommandBuffers(uint32_t count,
|
||||
void* dcbGpuAddrs[],
|
||||
uint32_t* dcbSizesInBytes,
|
||||
void* ccbGpuAddrs[],
|
||||
uint32_t* ccbSizesInBytes,
|
||||
uint32_t videoOutHandle,
|
||||
uint32_t displayBufferIndex,
|
||||
uint32_t flipMode,
|
||||
int64_t flipArg)
|
||||
{
|
||||
// There's only one hardware graphics queue for most of modern GPUs, including the one on PS4.
|
||||
// Thus a PS4 game will call submit function to submit command buffers sequentially,
|
||||
// and normally in one same thread.
|
||||
// We just emulate the GPU, parsing and executing one command buffer per call.
|
||||
|
||||
// TODO:
|
||||
// For real PS4 system, the submit call is asynchronous.
|
||||
// Thus for future development, we should record vulkan command buffer asynchronously too,
|
||||
// reducing time period of the submit call.
|
||||
|
||||
LOG_ASSERT(count == 1, "Currently only support 1 cmdbuff at one call.");
|
||||
|
||||
SceGpuCommand cmd = {};
|
||||
cmd.buffer = dcbGpuAddrs[0];
|
||||
cmd.size = dcbSizesInBytes[0];
|
||||
m_graphicsQueue->record(cmd);
|
||||
|
||||
submitPresent();
|
||||
|
||||
return SCE_OK;
|
||||
}
|
||||
|
||||
void SceGnmDriver::submitPresent()
|
||||
{
|
||||
do
|
||||
{
|
||||
//if (!cmdList)
|
||||
//{
|
||||
// break;
|
||||
//}
|
||||
|
||||
SceGpuSubmission gpuSubmission = {};
|
||||
//gpuSubmission.cmdList = cmdList;
|
||||
//gpuSubmission.wait = presentSync.acquire;
|
||||
//gpuSubmission.wake = presentSync.present;
|
||||
m_graphicsQueue->submit(gpuSubmission);
|
||||
|
||||
//VltPresentInfo presentation;
|
||||
//presentation.presenter = m_presenter;
|
||||
//presentation.waitSync = gpuSubmission.wake;
|
||||
//m_device->presentImage(presentation);
|
||||
|
||||
} while (false);
|
||||
}
|
||||
|
||||
int SceGnmDriver::sceGnmSubmitDone(void)
|
||||
{
|
||||
// Gnm::submitDone() is the place to hint the PS4 OS that
|
||||
// all the currently running GPU tasks (graphics and compute) are done for a frame,
|
||||
// such that the OS get the permission to do some extra stuffs.
|
||||
//
|
||||
// Since we use a window to emulate the hardware display, we need a place
|
||||
// to process the window event.
|
||||
// Currently I didn't find a very good place, so I place it here.
|
||||
glfwPollEvents();
|
||||
return SCE_OK;
|
||||
}
|
||||
|
||||
void SceGnmDriver::createGraphicsQueue()
|
||||
{
|
||||
// Create the only graphics queue.
|
||||
SceGpuQueueDevice gfxDevice = {};
|
||||
m_graphicsQueue = std::make_unique<SceGpuQueue>(gfxDevice, SceQueueType::Graphics);
|
||||
}
|
||||
|
||||
uint32_t SceGnmDriver::mapComputeQueue(uint32_t pipeId,
|
||||
uint32_t queueId,
|
||||
void* ringBaseAddr,
|
||||
uint32_t ringSizeInDW,
|
||||
void* readPtrAddr)
|
||||
{
|
||||
int vqueueId = SCE_GNM_ERROR_UNKNOWN;
|
||||
do
|
||||
{
|
||||
if (pipeId >= MaxPipeId)
|
||||
{
|
||||
vqueueId = SCE_GNM_ERROR_COMPUTEQUEUE_INVALID_PIPE_ID;
|
||||
break;
|
||||
}
|
||||
|
||||
if (queueId >= MaxQueueId)
|
||||
{
|
||||
vqueueId = SCE_GNM_ERROR_COMPUTEQUEUE_INVALID_QUEUE_ID;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((uintptr_t)ringBaseAddr % 256 != 0)
|
||||
{
|
||||
vqueueId = SCE_GNM_ERROR_COMPUTEQUEUE_INVALID_RING_BASE_ADDR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!::util::isPowerOfTwo(ringSizeInDW))
|
||||
{
|
||||
vqueueId = SCE_GNM_ERROR_COMPUTEQUEUE_INVALID_RING_SIZE;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((uintptr_t)readPtrAddr % 4 != 0)
|
||||
{
|
||||
vqueueId = SCE_GNM_ERROR_COMPUTEQUEUE_INVALID_READ_PTR_ADDR;
|
||||
break;
|
||||
}
|
||||
|
||||
*(uint32_t*)readPtrAddr = 0;
|
||||
|
||||
vqueueId = VQueueIdBegin + pipeId * MaxPipeId + queueId;
|
||||
if (vqueueId >= MaxComputeQueueCount)
|
||||
{
|
||||
LOG_ERR("vqueueId is larger than max queue count.");
|
||||
break;
|
||||
}
|
||||
|
||||
SceGpuQueueDevice cptDevice = {};
|
||||
//cptDevice.device = m_device;
|
||||
//cptDevice.presenter = nullptr;
|
||||
//cptDevice.videoOut = nullptr;
|
||||
|
||||
uint32_t vqueueIndex = vqueueId - VQueueIdBegin;
|
||||
m_computeQueues[vqueueIndex] = std::make_unique<SceGpuQueue>(cptDevice, SceQueueType::Compute);
|
||||
|
||||
} while (false);
|
||||
|
||||
return vqueueId;
|
||||
}
|
||||
|
||||
void SceGnmDriver::unmapComputeQueue(uint32_t vqueueId)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (vqueueId >= MaxComputeQueueCount)
|
||||
{
|
||||
LOG_ERR("vqueueId is larger than max queue count.");
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t vqueueIndex = vqueueId - VQueueIdBegin;
|
||||
m_computeQueues[vqueueIndex].reset();
|
||||
|
||||
} while (false);
|
||||
}
|
||||
|
||||
void SceGnmDriver::dingDong(
|
||||
uint32_t vqueueId,
|
||||
uint32_t nextStartOffsetInDw)
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace sce
|
|
@ -2,73 +2,88 @@
|
|||
|
||||
#include "SceCommon.h"
|
||||
|
||||
#include "Violet/VltRc.h"
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
|
||||
|
||||
namespace sce
|
||||
{
|
||||
|
||||
class SceGpuQueue;
|
||||
namespace vlt
|
||||
{
|
||||
class VltInstance;
|
||||
class VltAdapter;
|
||||
class VltDevice;
|
||||
} // namespace vlt
|
||||
|
||||
// Valid vqueue id should be positive value.
|
||||
constexpr uint32_t VQueueIdBegin = 1;
|
||||
constexpr uint32_t MaxPipeId = 7; // Some docs say it should be 7, others say it should be 3. Fuck that.
|
||||
constexpr uint32_t MaxQueueId = 8;
|
||||
constexpr uint32_t MaxComputeQueueCount = MaxPipeId * MaxQueueId;
|
||||
class SceGpuQueue;
|
||||
|
||||
class SceGnmDriver
|
||||
{
|
||||
// Valid vqueue id should be positive value.
|
||||
constexpr uint32_t VQueueIdBegin = 1;
|
||||
constexpr uint32_t MaxPipeId = 7; // Some docs say it should be 7, others say it should be 3. Fuck that.
|
||||
constexpr uint32_t MaxQueueId = 8;
|
||||
constexpr uint32_t MaxComputeQueueCount = MaxPipeId * MaxQueueId;
|
||||
|
||||
public:
|
||||
SceGnmDriver();
|
||||
~SceGnmDriver();
|
||||
class SceGnmDriver
|
||||
{
|
||||
|
||||
/// Graphics
|
||||
|
||||
int submitCommandBuffers(uint32_t count,
|
||||
void* dcbGpuAddrs[],
|
||||
uint32_t* dcbSizesInBytes,
|
||||
void* ccbGpuAddrs[],
|
||||
uint32_t* ccbSizesInBytes);
|
||||
public:
|
||||
SceGnmDriver();
|
||||
~SceGnmDriver();
|
||||
|
||||
int submitAndFlipCommandBuffers(uint32_t count,
|
||||
void* dcbGpuAddrs[],
|
||||
uint32_t* dcbSizesInBytes,
|
||||
void* ccbGpuAddrs[],
|
||||
uint32_t* ccbSizesInBytes,
|
||||
uint32_t videoOutHandle,
|
||||
uint32_t displayBufferIndex,
|
||||
uint32_t flipMode,
|
||||
int64_t flipArg);
|
||||
/// Graphics
|
||||
|
||||
int sceGnmSubmitDone(void);
|
||||
int submitCommandBuffers(uint32_t count,
|
||||
void* dcbGpuAddrs[],
|
||||
uint32_t* dcbSizesInBytes,
|
||||
void* ccbGpuAddrs[],
|
||||
uint32_t* ccbSizesInBytes);
|
||||
|
||||
/// Compute
|
||||
int submitAndFlipCommandBuffers(uint32_t count,
|
||||
void* dcbGpuAddrs[],
|
||||
uint32_t* dcbSizesInBytes,
|
||||
void* ccbGpuAddrs[],
|
||||
uint32_t* ccbSizesInBytes,
|
||||
uint32_t videoOutHandle,
|
||||
uint32_t displayBufferIndex,
|
||||
uint32_t flipMode,
|
||||
int64_t flipArg);
|
||||
|
||||
uint32_t mapComputeQueue(
|
||||
uint32_t pipeId,
|
||||
uint32_t queueId,
|
||||
void* ringBaseAddr,
|
||||
uint32_t ringSizeInDW,
|
||||
void* readPtrAddr);
|
||||
int sceGnmSubmitDone(void);
|
||||
|
||||
void unmapComputeQueue(uint32_t vqueueId);
|
||||
/// Compute
|
||||
|
||||
void dingDong(
|
||||
uint32_t vqueueId,
|
||||
uint32_t nextStartOffsetInDw);
|
||||
uint32_t mapComputeQueue(
|
||||
uint32_t pipeId,
|
||||
uint32_t queueId,
|
||||
void* ringBaseAddr,
|
||||
uint32_t ringSizeInDW,
|
||||
void* readPtrAddr);
|
||||
|
||||
private:
|
||||
bool initGnmDriver();
|
||||
void unmapComputeQueue(uint32_t vqueueId);
|
||||
|
||||
void createGraphicsQueue();
|
||||
void dingDong(
|
||||
uint32_t vqueueId,
|
||||
uint32_t nextStartOffsetInDw);
|
||||
|
||||
void submitPresent();
|
||||
private:
|
||||
bool initGnmDriver();
|
||||
|
||||
private:
|
||||
std::unique_ptr<SceGpuQueue> m_graphicsQueue;
|
||||
std::array<std::unique_ptr<SceGpuQueue>, MaxComputeQueueCount> m_computeQueues;
|
||||
};
|
||||
bool initVltDevice();
|
||||
|
||||
void createGraphicsQueue();
|
||||
|
||||
void submitPresent();
|
||||
|
||||
private:
|
||||
vlt::Rc<vlt::VltInstance> m_instance;
|
||||
vlt::Rc<vlt::VltAdapter> m_adapter;
|
||||
vlt::Rc<vlt::VltDevice> m_device;
|
||||
|
||||
std::unique_ptr<SceGpuQueue> m_graphicsQueue;
|
||||
std::array<std::unique_ptr<SceGpuQueue>, MaxComputeQueueCount>
|
||||
m_computeQueues;
|
||||
};
|
||||
|
||||
} // namespace sce
|
|
@ -429,14 +429,14 @@ namespace sce::vlt
|
|||
|
||||
for (uint32_t family : queueFamiliySet)
|
||||
{
|
||||
VkDeviceQueueCreateInfo graphicsQueue;
|
||||
graphicsQueue.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||
graphicsQueue.pNext = nullptr;
|
||||
graphicsQueue.flags = 0;
|
||||
graphicsQueue.queueFamilyIndex = family;
|
||||
graphicsQueue.queueCount = 1;
|
||||
graphicsQueue.pQueuePriorities = &queuePriority;
|
||||
queueInfos.push_back(graphicsQueue);
|
||||
VkDeviceQueueCreateInfo deviceQueue;
|
||||
deviceQueue.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||
deviceQueue.pNext = nullptr;
|
||||
deviceQueue.flags = 0;
|
||||
deviceQueue.queueFamilyIndex = family;
|
||||
deviceQueue.queueCount = 1;
|
||||
deviceQueue.pQueuePriorities = &queuePriority;
|
||||
queueInfos.push_back(deviceQueue);
|
||||
}
|
||||
|
||||
VkDeviceCreateInfo info;
|
||||
|
@ -458,7 +458,7 @@ namespace sce::vlt
|
|||
Logger::exception("DxvkAdapter: Failed to create device");
|
||||
|
||||
Rc<VltDevice> result = new VltDevice(
|
||||
instance, this, devExtensions, requestFeatures);
|
||||
instance, this, device, devExtensions, requestFeatures);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -797,6 +797,7 @@ namespace sce::vlt
|
|||
{
|
||||
Logger::info(util::str::formatex("Queue families:",
|
||||
"\n Graphics : ", queues.graphics,
|
||||
"\n Compute : ", queues.compute,
|
||||
"\n Transfer : ", queues.transfer));
|
||||
}
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ namespace sce::vlt
|
|||
};
|
||||
|
||||
/**
|
||||
* \brief DXVK adapter
|
||||
* \brief VLT adapter
|
||||
*
|
||||
* Corresponds to a physical device in Vulkan. Provides
|
||||
* all kinds of information about the device itself and
|
||||
|
|
|
@ -7,8 +7,10 @@ namespace sce::vlt
|
|||
VltDevice::VltDevice(
|
||||
const Rc<VltInstance>& instance,
|
||||
const Rc<VltAdapter>& adapter,
|
||||
VkDevice device,
|
||||
const VltDeviceExtensions& extensions,
|
||||
const VltDeviceFeatures& features) :
|
||||
m_device(device),
|
||||
m_instance(instance),
|
||||
m_adapter(adapter),
|
||||
m_extensions(extensions),
|
||||
|
|
|
@ -45,6 +45,7 @@ namespace sce::vlt
|
|||
VltDevice(
|
||||
const Rc<VltInstance>& instance,
|
||||
const Rc<VltAdapter>& adapter,
|
||||
VkDevice device,
|
||||
const VltDeviceExtensions& extensions,
|
||||
const VltDeviceFeatures& features);
|
||||
|
||||
|
|
|
@ -19,7 +19,11 @@ namespace sce::vlt
|
|||
{
|
||||
if (properties.apiVersion < VK_MAKE_VERSION(1, 3, 0))
|
||||
{
|
||||
Logger::warn(util::str::formatex("Skipping Vulkan 1.3 adapter: ", properties.deviceName));
|
||||
Logger::warn(util::str::formatex("Skipping Vulkan ",
|
||||
VK_API_VERSION_MAJOR(properties.apiVersion),
|
||||
".",
|
||||
VK_API_VERSION_MINOR(properties.apiVersion),
|
||||
" adapter: ", properties.deviceName));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
#include "VltInstance.h"
|
||||
|
||||
#include "VltAdapter.h"
|
||||
#include "VltDeviceFilter.h"
|
||||
|
||||
#include "Platform/PlatVulkan.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
LOG_CHANNEL(Graphic.Violet);
|
||||
|
@ -30,6 +33,19 @@ namespace sce::vlt
|
|||
: nullptr;
|
||||
}
|
||||
|
||||
std::vector<VltExt> VltInstance::getPlatformExtensions()
|
||||
{
|
||||
std::vector<VltExt> result;
|
||||
|
||||
auto platformExtensions = plat::vulkanGetRequiredInstanceExtensions();
|
||||
for (const auto& ext : platformExtensions)
|
||||
{
|
||||
result.emplace_back(ext, VltExtMode::Required);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
VkInstance VltInstance::createInstance()
|
||||
{
|
||||
VltInstanceExtensions insExtensions;
|
||||
|
@ -39,6 +55,12 @@ namespace sce::vlt
|
|||
&insExtensions.khrSurface,
|
||||
} };
|
||||
|
||||
auto platformExtensions = getPlatformExtensions();
|
||||
for (auto& ext : platformExtensions)
|
||||
{
|
||||
insExtensionList.push_back(&ext);
|
||||
}
|
||||
|
||||
std::vector<const char*> insLayers;
|
||||
|
||||
#ifdef VLT_VALIDATION_AND_DEBUG
|
||||
|
@ -56,7 +78,6 @@ namespace sce::vlt
|
|||
Logger::exception("DxvkInstance: Failed to create instance");
|
||||
|
||||
m_extensions = insExtensions;
|
||||
|
||||
VltNameList extensionNameList = extensionsEnabled.toNameList();
|
||||
|
||||
Logger::info("Enabled instance extensions:");
|
||||
|
@ -159,4 +180,5 @@ namespace sce::vlt
|
|||
for (uint32_t i = 0; i < names.count(); i++)
|
||||
Logger::info(util::str::formatex(" ", names.name(i)));
|
||||
}
|
||||
|
||||
} // namespace sce::vlt
|
|
@ -7,8 +7,9 @@
|
|||
namespace sce::vlt
|
||||
{
|
||||
class VltAdapter;
|
||||
|
||||
/**
|
||||
* \brief DXVK instance
|
||||
* \brief VLT instance
|
||||
*
|
||||
* Manages a Vulkan instance and stores a list
|
||||
* of adapters. This also provides methods for
|
||||
|
@ -62,6 +63,8 @@ namespace sce::vlt
|
|||
}
|
||||
|
||||
private:
|
||||
std::vector<VltExt> getPlatformExtensions();
|
||||
|
||||
VkInstance createInstance();
|
||||
|
||||
std::vector<Rc<VltAdapter>> queryAdapters();
|
||||
|
|
|
@ -173,6 +173,10 @@ namespace sce::vlt
|
|||
{
|
||||
return m_object != nullptr;
|
||||
}
|
||||
operator bool() const
|
||||
{
|
||||
return m_object != nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
T* m_object = nullptr;
|
||||
|
|
25
GPCS4/Platform/PlatVulkan.cpp
Normal file
25
GPCS4/Platform/PlatVulkan.cpp
Normal file
|
@ -0,0 +1,25 @@
|
|||
#include "PlatVulkan.h"
|
||||
|
||||
#ifdef GPCS4_WINDOWS
|
||||
|
||||
// this acctually should be done using glfwGetRequiredInstanceExtensions
|
||||
// but due to initialize order issue, we implement it here
|
||||
std::vector<const char*> plat::vulkanGetRequiredInstanceExtensions()
|
||||
{
|
||||
// clang-format off
|
||||
return std::vector<const char*>
|
||||
({
|
||||
"VK_KHR_win32_surface"
|
||||
});
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
std::vector<const char*> plat::vulkanGetRequiredInstanceExtensions()
|
||||
{
|
||||
// TODO:
|
||||
}
|
||||
|
||||
#endif
|
||||
|
12
GPCS4/Platform/PlatVulkan.h
Normal file
12
GPCS4/Platform/PlatVulkan.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include "GPCS4Common.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace plat
|
||||
{
|
||||
|
||||
std::vector<const char*> vulkanGetRequiredInstanceExtensions();
|
||||
|
||||
} // namespace plat
|
Loading…
Reference in a new issue