2020-02-12 19:41:35 -05:00
|
|
|
#include "GSH_VulkanTransferHost.h"
|
2019-11-25 13:20:24 -05:00
|
|
|
#include "GSH_VulkanMemoryUtils.h"
|
2021-09-24 21:59:21 -04:00
|
|
|
#include "GSH_VulkanPlatformDefs.h"
|
2019-11-06 20:10:56 -05:00
|
|
|
#include "MemStream.h"
|
|
|
|
#include "vulkan/StructDefs.h"
|
|
|
|
#include "vulkan/Utils.h"
|
|
|
|
#include "nuanceur/generators/SpirvShaderGenerator.h"
|
2019-11-28 20:17:10 -05:00
|
|
|
#include "../GSHandler.h"
|
2019-11-06 20:10:56 -05:00
|
|
|
|
|
|
|
using namespace GSH_Vulkan;
|
|
|
|
|
2019-11-13 09:45:15 -05:00
|
|
|
#define XFER_BUFFER_SIZE 0x400000
|
|
|
|
|
2019-11-06 20:10:56 -05:00
|
|
|
#define DESCRIPTOR_LOCATION_MEMORY 0
|
|
|
|
#define DESCRIPTOR_LOCATION_XFERBUFFER 1
|
2019-12-11 21:34:37 -05:00
|
|
|
#define DESCRIPTOR_LOCATION_SWIZZLETABLE_DST 2
|
2021-03-30 22:51:40 +01:00
|
|
|
#define DESCRIPTOR_LOCATION_MEMORY_8BIT 3
|
2021-04-02 16:45:07 +01:00
|
|
|
#define DESCRIPTOR_LOCATION_MEMORY_16BIT 4
|
2019-11-06 20:10:56 -05:00
|
|
|
|
2021-09-24 21:59:21 -04:00
|
|
|
#define TRANSFER_USE_8_16_BIT GSH_VULKAN_IS_DESKTOP
|
|
|
|
|
2020-02-12 19:41:35 -05:00
|
|
|
CTransferHost::CTransferHost(const ContextPtr& context, const FrameCommandBufferPtr& frameCommandBuffer)
|
2019-12-13 23:21:59 -05:00
|
|
|
: m_context(context)
|
|
|
|
, m_frameCommandBuffer(frameCommandBuffer)
|
|
|
|
, m_pipelineCache(context->device)
|
2019-11-06 20:10:56 -05:00
|
|
|
{
|
2020-01-16 21:46:02 -05:00
|
|
|
for(auto& frame : m_frames)
|
|
|
|
{
|
|
|
|
frame.xferBuffer = Framework::Vulkan::CBuffer(
|
2020-01-31 09:34:48 -05:00
|
|
|
m_context->device, m_context->physicalDeviceMemoryProperties,
|
2021-03-29 17:04:29 -04:00
|
|
|
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
|
|
|
XFER_BUFFER_SIZE);
|
2020-01-15 09:24:51 -05:00
|
|
|
|
2020-01-16 21:46:02 -05:00
|
|
|
auto result = m_context->device.vkMapMemory(m_context->device, frame.xferBuffer.GetMemory(),
|
2020-01-31 09:34:48 -05:00
|
|
|
0, VK_WHOLE_SIZE, 0, reinterpret_cast<void**>(&frame.xferBufferPtr));
|
2020-01-16 21:46:02 -05:00
|
|
|
CHECKVULKANERROR(result);
|
|
|
|
}
|
2020-01-15 09:24:51 -05:00
|
|
|
|
2021-09-29 18:42:47 -04:00
|
|
|
m_localSize = std::min<uint32>(context->computeWorkgroupInvocations, 1024);
|
2019-11-25 20:35:17 -05:00
|
|
|
m_pipelineCaps <<= 0;
|
2019-11-06 20:10:56 -05:00
|
|
|
}
|
|
|
|
|
2020-02-12 19:41:35 -05:00
|
|
|
CTransferHost::~CTransferHost()
|
2019-11-06 20:10:56 -05:00
|
|
|
{
|
2020-01-16 21:46:02 -05:00
|
|
|
for(auto& frame : m_frames)
|
|
|
|
{
|
|
|
|
m_context->device.vkUnmapMemory(m_context->device, frame.xferBuffer.GetMemory());
|
|
|
|
}
|
2019-11-06 20:10:56 -05:00
|
|
|
}
|
|
|
|
|
2020-02-12 19:41:35 -05:00
|
|
|
void CTransferHost::SetPipelineCaps(const PIPELINE_CAPS& pipelineCaps)
|
2019-11-28 20:17:10 -05:00
|
|
|
{
|
|
|
|
m_pipelineCaps = pipelineCaps;
|
|
|
|
}
|
|
|
|
|
2020-02-12 19:41:35 -05:00
|
|
|
void CTransferHost::DoTransfer(const XferBuffer& inputData)
|
2019-11-06 20:10:56 -05:00
|
|
|
{
|
|
|
|
auto result = VK_SUCCESS;
|
|
|
|
|
2020-01-16 08:41:08 -05:00
|
|
|
uint32 xferBufferRemainSize = XFER_BUFFER_SIZE - m_xferBufferOffset;
|
|
|
|
if(xferBufferRemainSize < inputData.size())
|
|
|
|
{
|
|
|
|
m_frameCommandBuffer->Flush();
|
|
|
|
assert((XFER_BUFFER_SIZE - m_xferBufferOffset) >= inputData.size());
|
|
|
|
}
|
|
|
|
|
2020-01-16 21:46:02 -05:00
|
|
|
auto& frame = m_frames[m_frameCommandBuffer->GetCurrentFrame()];
|
|
|
|
|
2020-01-15 09:24:51 -05:00
|
|
|
assert(inputData.size() <= XFER_BUFFER_SIZE);
|
2020-01-16 21:46:02 -05:00
|
|
|
memcpy(frame.xferBufferPtr + m_xferBufferOffset, inputData.data(), inputData.size());
|
2019-11-13 09:45:15 -05:00
|
|
|
|
2019-11-25 20:35:17 -05:00
|
|
|
//Find pipeline and create it if we've never encountered it before
|
2019-12-05 18:55:27 -05:00
|
|
|
auto xferPipeline = m_pipelineCache.TryGetPipeline(m_pipelineCaps);
|
|
|
|
if(!xferPipeline)
|
2019-11-25 20:35:17 -05:00
|
|
|
{
|
2019-12-05 18:55:27 -05:00
|
|
|
xferPipeline = m_pipelineCache.RegisterPipeline(m_pipelineCaps, CreateXferPipeline(m_pipelineCaps));
|
2019-11-25 20:35:17 -05:00
|
|
|
}
|
|
|
|
|
2019-11-28 20:17:10 -05:00
|
|
|
uint32 pixelCount = 0;
|
|
|
|
switch(m_pipelineCaps.dstFormat)
|
|
|
|
{
|
|
|
|
default:
|
2019-12-15 12:18:44 -05:00
|
|
|
assert(false);
|
2019-11-28 20:17:10 -05:00
|
|
|
case CGSHandler::PSMCT32:
|
2020-07-20 20:43:06 -04:00
|
|
|
case CGSHandler::PSMZ32:
|
2019-11-28 20:17:10 -05:00
|
|
|
pixelCount = inputData.size() / 4;
|
|
|
|
break;
|
2020-01-30 12:45:14 -05:00
|
|
|
case CGSHandler::PSMCT24:
|
2021-07-28 17:11:31 -04:00
|
|
|
case CGSHandler::PSMZ24:
|
2020-01-30 12:45:14 -05:00
|
|
|
pixelCount = inputData.size() / 3;
|
|
|
|
break;
|
2021-03-01 21:14:09 +00:00
|
|
|
case CGSHandler::PSMCT16S:
|
2019-12-15 12:25:31 -05:00
|
|
|
case CGSHandler::PSMCT16:
|
|
|
|
pixelCount = inputData.size() / 2;
|
|
|
|
break;
|
2019-11-28 20:17:10 -05:00
|
|
|
case CGSHandler::PSMT8:
|
2020-01-20 21:12:20 -05:00
|
|
|
case CGSHandler::PSMT8H:
|
2019-11-28 20:17:10 -05:00
|
|
|
pixelCount = inputData.size();
|
|
|
|
break;
|
2020-01-20 13:24:09 -05:00
|
|
|
case CGSHandler::PSMT4:
|
2020-01-20 21:12:20 -05:00
|
|
|
case CGSHandler::PSMT4HL:
|
|
|
|
case CGSHandler::PSMT4HH:
|
2020-01-20 13:24:09 -05:00
|
|
|
pixelCount = inputData.size() * 2;
|
|
|
|
break;
|
2019-11-28 20:17:10 -05:00
|
|
|
}
|
|
|
|
|
2020-01-10 12:41:58 -05:00
|
|
|
Params.pixelCount = pixelCount;
|
2021-09-29 16:47:42 -04:00
|
|
|
uint32 workUnits = (pixelCount + m_localSize - 1) / m_localSize;
|
2019-11-13 09:45:15 -05:00
|
|
|
|
2020-01-16 21:46:02 -05:00
|
|
|
auto descriptorSetCaps = make_convertible<DESCRIPTORSET_CAPS>(0);
|
|
|
|
descriptorSetCaps.dstPsm = m_pipelineCaps.dstFormat;
|
|
|
|
descriptorSetCaps.frameIdx = m_frameCommandBuffer->GetCurrentFrame();
|
|
|
|
|
|
|
|
auto descriptorSet = PrepareDescriptorSet(xferPipeline->descriptorSetLayout, descriptorSetCaps);
|
2019-12-10 09:39:12 -05:00
|
|
|
auto commandBuffer = m_frameCommandBuffer->GetCommandBuffer();
|
2019-11-06 20:10:56 -05:00
|
|
|
|
2020-01-21 21:08:08 -05:00
|
|
|
//Add a barrier to ensure reads are complete before writing to GS memory
|
|
|
|
{
|
|
|
|
auto memoryBarrier = Framework::Vulkan::MemoryBarrier();
|
|
|
|
memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
|
|
|
memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
|
|
|
|
|
|
|
|
m_context->device.vkCmdPipelineBarrier(commandBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
|
|
|
0, 1, &memoryBarrier, 0, nullptr, 0, nullptr);
|
|
|
|
}
|
|
|
|
|
2020-01-16 08:41:08 -05:00
|
|
|
m_context->device.vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, xferPipeline->pipelineLayout, 0, 1, &descriptorSet, 1, &m_xferBufferOffset);
|
2019-12-05 18:55:27 -05:00
|
|
|
m_context->device.vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, xferPipeline->pipeline);
|
|
|
|
m_context->device.vkCmdPushConstants(commandBuffer, xferPipeline->pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(XFERPARAMS), &Params);
|
2019-11-13 09:45:15 -05:00
|
|
|
m_context->device.vkCmdDispatch(commandBuffer, workUnits, 1, 1);
|
2019-11-06 20:10:56 -05:00
|
|
|
|
2020-01-16 08:41:08 -05:00
|
|
|
m_xferBufferOffset += inputData.size();
|
2021-09-29 16:47:42 -04:00
|
|
|
m_xferBufferOffset = (m_xferBufferOffset + (m_context->storageBufferAlignment - 1)) & -m_context->storageBufferAlignment;
|
2019-11-06 20:10:56 -05:00
|
|
|
}
|
|
|
|
|
2020-02-12 19:41:35 -05:00
|
|
|
VkDescriptorSet CTransferHost::PrepareDescriptorSet(VkDescriptorSetLayout descriptorSetLayout, const DESCRIPTORSET_CAPS& caps)
|
2019-11-06 20:10:56 -05:00
|
|
|
{
|
2020-01-16 21:46:02 -05:00
|
|
|
auto descriptorSetIterator = m_descriptorSetCache.find(caps);
|
2020-01-16 08:26:39 -05:00
|
|
|
if(descriptorSetIterator != std::end(m_descriptorSetCache))
|
|
|
|
{
|
|
|
|
return descriptorSetIterator->second;
|
|
|
|
}
|
|
|
|
|
2019-11-06 20:10:56 -05:00
|
|
|
VkResult result = VK_SUCCESS;
|
|
|
|
VkDescriptorSet descriptorSet = VK_NULL_HANDLE;
|
|
|
|
|
|
|
|
//Allocate descriptor set
|
|
|
|
{
|
|
|
|
auto setAllocateInfo = Framework::Vulkan::DescriptorSetAllocateInfo();
|
2019-12-13 23:21:59 -05:00
|
|
|
setAllocateInfo.descriptorPool = m_context->descriptorPool;
|
2019-11-06 20:10:56 -05:00
|
|
|
setAllocateInfo.descriptorSetCount = 1;
|
2019-12-13 23:21:59 -05:00
|
|
|
setAllocateInfo.pSetLayouts = &descriptorSetLayout;
|
2019-11-06 20:10:56 -05:00
|
|
|
|
|
|
|
result = m_context->device.vkAllocateDescriptorSets(m_context->device, &setAllocateInfo, &descriptorSet);
|
|
|
|
CHECKVULKANERROR(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Update descriptor set
|
|
|
|
{
|
|
|
|
std::vector<VkWriteDescriptorSet> writes;
|
|
|
|
|
2019-12-17 19:22:27 -05:00
|
|
|
VkDescriptorBufferInfo descriptorMemoryBufferInfo = {};
|
|
|
|
descriptorMemoryBufferInfo.buffer = m_context->memoryBuffer;
|
|
|
|
descriptorMemoryBufferInfo.range = VK_WHOLE_SIZE;
|
2019-11-15 13:20:14 -05:00
|
|
|
|
|
|
|
VkDescriptorBufferInfo descriptorBufferInfo = {};
|
2020-01-16 21:46:02 -05:00
|
|
|
descriptorBufferInfo.buffer = m_frames[caps.frameIdx].xferBuffer;
|
2019-11-15 13:20:14 -05:00
|
|
|
descriptorBufferInfo.range = VK_WHOLE_SIZE;
|
|
|
|
|
2019-12-11 21:34:37 -05:00
|
|
|
VkDescriptorImageInfo descriptorDstSwizzleTableInfo = {};
|
2020-01-16 21:46:02 -05:00
|
|
|
descriptorDstSwizzleTableInfo.imageView = m_context->GetSwizzleTable(caps.dstPsm);
|
2019-12-11 21:34:37 -05:00
|
|
|
descriptorDstSwizzleTableInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
|
|
|
|
2019-11-06 20:10:56 -05:00
|
|
|
//Memory Image Descriptor
|
|
|
|
{
|
|
|
|
auto writeSet = Framework::Vulkan::WriteDescriptorSet();
|
2019-12-13 23:21:59 -05:00
|
|
|
writeSet.dstSet = descriptorSet;
|
|
|
|
writeSet.dstBinding = DESCRIPTOR_LOCATION_MEMORY;
|
2019-11-06 20:10:56 -05:00
|
|
|
writeSet.descriptorCount = 1;
|
2019-12-17 19:22:27 -05:00
|
|
|
writeSet.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
|
|
|
writeSet.pBufferInfo = &descriptorMemoryBufferInfo;
|
2019-11-06 20:10:56 -05:00
|
|
|
writes.push_back(writeSet);
|
|
|
|
}
|
|
|
|
|
2021-03-30 22:51:40 +01:00
|
|
|
//Memory Image Descriptor 8 bit
|
2021-09-24 21:59:21 -04:00
|
|
|
if(TRANSFER_USE_8_16_BIT)
|
2021-03-30 22:51:40 +01:00
|
|
|
{
|
|
|
|
auto writeSet = Framework::Vulkan::WriteDescriptorSet();
|
|
|
|
writeSet.dstSet = descriptorSet;
|
|
|
|
writeSet.dstBinding = DESCRIPTOR_LOCATION_MEMORY_8BIT;
|
|
|
|
writeSet.descriptorCount = 1;
|
|
|
|
writeSet.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
|
|
|
writeSet.pBufferInfo = &descriptorMemoryBufferInfo;
|
|
|
|
writes.push_back(writeSet);
|
|
|
|
}
|
|
|
|
|
2021-04-02 16:45:07 +01:00
|
|
|
//Memory Image Descriptor 16 bit
|
2021-09-24 21:59:21 -04:00
|
|
|
if(TRANSFER_USE_8_16_BIT)
|
2021-04-02 16:45:07 +01:00
|
|
|
{
|
|
|
|
auto writeSet = Framework::Vulkan::WriteDescriptorSet();
|
|
|
|
writeSet.dstSet = descriptorSet;
|
|
|
|
writeSet.dstBinding = DESCRIPTOR_LOCATION_MEMORY_16BIT;
|
|
|
|
writeSet.descriptorCount = 1;
|
|
|
|
writeSet.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
|
|
|
writeSet.pBufferInfo = &descriptorMemoryBufferInfo;
|
|
|
|
writes.push_back(writeSet);
|
|
|
|
}
|
|
|
|
|
2019-11-06 20:10:56 -05:00
|
|
|
//Xfer Buffer Descriptor
|
|
|
|
{
|
|
|
|
auto writeSet = Framework::Vulkan::WriteDescriptorSet();
|
2019-12-13 23:21:59 -05:00
|
|
|
writeSet.dstSet = descriptorSet;
|
|
|
|
writeSet.dstBinding = DESCRIPTOR_LOCATION_XFERBUFFER;
|
2019-11-06 20:10:56 -05:00
|
|
|
writeSet.descriptorCount = 1;
|
2020-01-16 08:41:08 -05:00
|
|
|
writeSet.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
|
2019-12-13 23:21:59 -05:00
|
|
|
writeSet.pBufferInfo = &descriptorBufferInfo;
|
2019-11-13 09:45:15 -05:00
|
|
|
writes.push_back(writeSet);
|
2019-11-06 20:10:56 -05:00
|
|
|
}
|
|
|
|
|
2019-12-11 21:34:37 -05:00
|
|
|
//Dst Swizzle Table
|
|
|
|
{
|
|
|
|
auto writeSet = Framework::Vulkan::WriteDescriptorSet();
|
2019-12-13 23:21:59 -05:00
|
|
|
writeSet.dstSet = descriptorSet;
|
|
|
|
writeSet.dstBinding = DESCRIPTOR_LOCATION_SWIZZLETABLE_DST;
|
2019-12-11 21:34:37 -05:00
|
|
|
writeSet.descriptorCount = 1;
|
2019-12-13 23:21:59 -05:00
|
|
|
writeSet.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
|
|
|
writeSet.pImageInfo = &descriptorDstSwizzleTableInfo;
|
2019-12-11 21:34:37 -05:00
|
|
|
writes.push_back(writeSet);
|
|
|
|
}
|
|
|
|
|
2019-11-06 20:10:56 -05:00
|
|
|
m_context->device.vkUpdateDescriptorSets(m_context->device, writes.size(), writes.data(), 0, nullptr);
|
|
|
|
}
|
|
|
|
|
2020-01-16 21:46:02 -05:00
|
|
|
m_descriptorSetCache.insert(std::make_pair(caps, descriptorSet));
|
2020-01-16 08:26:39 -05:00
|
|
|
|
2019-11-06 20:10:56 -05:00
|
|
|
return descriptorSet;
|
|
|
|
}
|
|
|
|
|
2020-02-12 19:41:35 -05:00
|
|
|
void CTransferHost::PreFlushFrameCommandBuffer()
|
2020-01-16 08:41:08 -05:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-02-12 19:41:35 -05:00
|
|
|
void CTransferHost::PostFlushFrameCommandBuffer()
|
2020-01-16 08:41:08 -05:00
|
|
|
{
|
|
|
|
m_xferBufferOffset = 0;
|
|
|
|
}
|
|
|
|
|
2020-02-12 19:41:35 -05:00
|
|
|
Framework::Vulkan::CShaderModule CTransferHost::CreateXferShader(const PIPELINE_CAPS& caps)
|
2019-11-06 20:10:56 -05:00
|
|
|
{
|
|
|
|
using namespace Nuanceur;
|
2019-12-13 23:21:59 -05:00
|
|
|
|
2019-11-06 20:10:56 -05:00
|
|
|
auto b = CShaderBuilder();
|
2019-12-13 23:21:59 -05:00
|
|
|
|
2021-09-29 16:47:42 -04:00
|
|
|
b.SetMetadata(CShaderBuilder::METADATA_LOCALSIZE_X, m_localSize);
|
2019-12-03 19:17:53 -05:00
|
|
|
|
2019-11-06 20:10:56 -05:00
|
|
|
{
|
2019-11-13 09:45:15 -05:00
|
|
|
auto inputInvocationId = CInt4Lvalue(b.CreateInputInt(Nuanceur::SEMANTIC_SYSTEM_GIID));
|
2019-12-17 19:22:27 -05:00
|
|
|
auto memoryBuffer = CArrayUintValue(b.CreateUniformArrayUint("memoryBuffer", DESCRIPTOR_LOCATION_MEMORY));
|
2021-09-24 21:59:21 -04:00
|
|
|
#if TRANSFER_USE_8_16_BIT
|
|
|
|
auto memoryBuffer8 = CArrayUcharValue(b.CreateUniformArrayUchar("memoryBuffer8", DESCRIPTOR_LOCATION_MEMORY_8BIT));
|
|
|
|
auto memoryBuffer16 = CArrayUshortValue(b.CreateUniformArrayUshort("memoryBuffer16", DESCRIPTOR_LOCATION_MEMORY_16BIT));
|
|
|
|
#endif
|
2019-11-13 09:45:15 -05:00
|
|
|
auto xferBuffer = CArrayUintValue(b.CreateUniformArrayUint("xferBuffer", DESCRIPTOR_LOCATION_XFERBUFFER));
|
2019-12-11 21:34:37 -05:00
|
|
|
auto dstSwizzleTable = CImageUint2DValue(b.CreateImage2DUint(DESCRIPTOR_LOCATION_SWIZZLETABLE_DST));
|
2019-11-06 20:10:56 -05:00
|
|
|
|
2019-11-15 13:20:14 -05:00
|
|
|
auto xferParams0 = CInt4Lvalue(b.CreateUniformInt4("xferParams0", Nuanceur::UNIFORM_UNIT_PUSHCONSTANT));
|
|
|
|
auto xferParams1 = CInt4Lvalue(b.CreateUniformInt4("xferParams1", Nuanceur::UNIFORM_UNIT_PUSHCONSTANT));
|
|
|
|
|
|
|
|
auto bufAddress = xferParams0->x();
|
2019-12-13 23:21:59 -05:00
|
|
|
auto bufWidth = xferParams0->y();
|
|
|
|
auto rrw = xferParams0->z();
|
|
|
|
auto dsax = xferParams0->w();
|
|
|
|
auto dsay = xferParams1->x();
|
2020-01-10 12:41:58 -05:00
|
|
|
auto pixelCount = xferParams1->y();
|
2019-11-15 13:20:14 -05:00
|
|
|
|
|
|
|
auto rrx = inputInvocationId->x() % rrw;
|
|
|
|
auto rry = inputInvocationId->x() / rrw;
|
|
|
|
|
|
|
|
auto trxX = (rrx + dsax) % NewInt(b, 2048);
|
|
|
|
auto trxY = (rry + dsay) % NewInt(b, 2048);
|
|
|
|
|
2019-11-28 20:17:10 -05:00
|
|
|
auto pixelIndex = inputInvocationId->x();
|
|
|
|
|
2020-01-10 12:41:58 -05:00
|
|
|
BeginIf(b, pixelIndex >= pixelCount);
|
|
|
|
{
|
|
|
|
Return(b);
|
|
|
|
}
|
|
|
|
EndIf(b);
|
|
|
|
|
2019-11-28 20:17:10 -05:00
|
|
|
switch(caps.dstFormat)
|
|
|
|
{
|
|
|
|
case CGSHandler::PSMCT32:
|
2020-07-20 20:43:06 -04:00
|
|
|
case CGSHandler::PSMZ32:
|
2019-12-13 23:21:59 -05:00
|
|
|
{
|
|
|
|
auto input = XferStream_Read32(b, xferBuffer, pixelIndex);
|
|
|
|
auto address = CMemoryUtils::GetPixelAddress<CGsPixelFormats::STORAGEPSMCT32>(
|
|
|
|
b, dstSwizzleTable, bufAddress, bufWidth, NewInt2(trxX, trxY));
|
2019-12-17 19:22:27 -05:00
|
|
|
CMemoryUtils::Memory_Write32(b, memoryBuffer, address, input);
|
2019-12-13 23:21:59 -05:00
|
|
|
}
|
|
|
|
break;
|
2020-01-30 12:45:14 -05:00
|
|
|
case CGSHandler::PSMCT24:
|
2021-07-28 17:11:31 -04:00
|
|
|
case CGSHandler::PSMZ24:
|
2020-01-30 12:45:14 -05:00
|
|
|
{
|
|
|
|
auto input = XferStream_Read24(b, xferBuffer, pixelIndex);
|
|
|
|
auto address = CMemoryUtils::GetPixelAddress<CGsPixelFormats::STORAGEPSMCT32>(
|
|
|
|
b, dstSwizzleTable, bufAddress, bufWidth, NewInt2(trxX, trxY));
|
2021-09-24 21:59:21 -04:00
|
|
|
#if TRANSFER_USE_8_16_BIT
|
|
|
|
CMemoryUtils::Memory_Write24(b, memoryBuffer8, memoryBuffer16, address, input);
|
|
|
|
#else
|
2021-06-28 16:51:25 -04:00
|
|
|
CMemoryUtils::Memory_Write24(b, memoryBuffer, address, input);
|
2021-09-24 21:59:21 -04:00
|
|
|
#endif
|
2020-01-30 12:45:14 -05:00
|
|
|
}
|
|
|
|
break;
|
2021-03-01 21:14:09 +00:00
|
|
|
case CGSHandler::PSMCT16S:
|
2019-12-15 12:25:31 -05:00
|
|
|
case CGSHandler::PSMCT16:
|
|
|
|
{
|
|
|
|
auto input = XferStream_Read16(b, xferBuffer, pixelIndex);
|
|
|
|
auto address = CMemoryUtils::GetPixelAddress<CGsPixelFormats::STORAGEPSMCT16>(
|
|
|
|
b, dstSwizzleTable, bufAddress, bufWidth, NewInt2(trxX, trxY));
|
2021-09-24 21:59:21 -04:00
|
|
|
#if TRANSFER_USE_8_16_BIT
|
|
|
|
CMemoryUtils::Memory_Write16(b, memoryBuffer16, address, input);
|
|
|
|
#else
|
2021-06-28 16:51:25 -04:00
|
|
|
CMemoryUtils::Memory_Write16(b, memoryBuffer, address, input);
|
2021-09-24 21:59:21 -04:00
|
|
|
#endif
|
2019-12-15 12:25:31 -05:00
|
|
|
}
|
2020-01-09 12:45:24 -05:00
|
|
|
break;
|
2019-11-28 20:17:10 -05:00
|
|
|
case CGSHandler::PSMT8:
|
2019-12-13 23:21:59 -05:00
|
|
|
{
|
|
|
|
auto input = XferStream_Read8(b, xferBuffer, pixelIndex);
|
|
|
|
auto address = CMemoryUtils::GetPixelAddress<CGsPixelFormats::STORAGEPSMT8>(
|
|
|
|
b, dstSwizzleTable, bufAddress, bufWidth, NewInt2(trxX, trxY));
|
2021-09-24 21:59:21 -04:00
|
|
|
#if TRANSFER_USE_8_16_BIT
|
|
|
|
CMemoryUtils::Memory_Write8(b, memoryBuffer8, address, input);
|
|
|
|
#else
|
2021-06-28 16:51:25 -04:00
|
|
|
CMemoryUtils::Memory_Write8(b, memoryBuffer, address, input);
|
2021-09-24 21:59:21 -04:00
|
|
|
#endif
|
2019-12-13 23:21:59 -05:00
|
|
|
}
|
|
|
|
break;
|
2020-01-20 13:24:09 -05:00
|
|
|
case CGSHandler::PSMT4:
|
|
|
|
{
|
|
|
|
auto input = XferStream_Read4(b, xferBuffer, pixelIndex);
|
|
|
|
auto address = CMemoryUtils::GetPixelAddress_PSMT4(
|
|
|
|
b, dstSwizzleTable, bufAddress, bufWidth, NewInt2(trxX, trxY));
|
|
|
|
CMemoryUtils::Memory_Write4(b, memoryBuffer, address, input);
|
|
|
|
}
|
|
|
|
break;
|
2020-01-20 21:12:20 -05:00
|
|
|
case CGSHandler::PSMT8H:
|
|
|
|
{
|
|
|
|
auto input = XferStream_Read8(b, xferBuffer, pixelIndex);
|
|
|
|
auto address = CMemoryUtils::GetPixelAddress<CGsPixelFormats::STORAGEPSMCT32>(
|
|
|
|
b, dstSwizzleTable, bufAddress, bufWidth, NewInt2(trxX, trxY));
|
2021-09-24 21:59:21 -04:00
|
|
|
#if TRANSFER_USE_8_16_BIT
|
|
|
|
CMemoryUtils::Memory_Write8(b, memoryBuffer8, address + NewInt(b, 3), input);
|
|
|
|
#else
|
2021-06-28 16:51:25 -04:00
|
|
|
CMemoryUtils::Memory_Write8(b, memoryBuffer, address + NewInt(b, 3), input);
|
2021-09-24 21:59:21 -04:00
|
|
|
#endif
|
2020-01-20 21:12:20 -05:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CGSHandler::PSMT4HL:
|
|
|
|
{
|
|
|
|
auto input = XferStream_Read4(b, xferBuffer, pixelIndex);
|
|
|
|
auto address = CMemoryUtils::GetPixelAddress<CGsPixelFormats::STORAGEPSMCT32>(
|
|
|
|
b, dstSwizzleTable, bufAddress, bufWidth, NewInt2(trxX, trxY));
|
|
|
|
auto nibAddress = (address + NewInt(b, 3)) * NewInt(b, 2);
|
|
|
|
CMemoryUtils::Memory_Write4(b, memoryBuffer, nibAddress, input);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CGSHandler::PSMT4HH:
|
|
|
|
{
|
|
|
|
auto input = XferStream_Read4(b, xferBuffer, pixelIndex);
|
|
|
|
auto address = CMemoryUtils::GetPixelAddress<CGsPixelFormats::STORAGEPSMCT32>(
|
|
|
|
b, dstSwizzleTable, bufAddress, bufWidth, NewInt2(trxX, trxY));
|
|
|
|
auto nibAddress = ((address + NewInt(b, 3)) * NewInt(b, 2)) | NewInt(b, 1);
|
|
|
|
CMemoryUtils::Memory_Write4(b, memoryBuffer, nibAddress, input);
|
|
|
|
}
|
|
|
|
break;
|
2019-11-28 20:17:10 -05:00
|
|
|
default:
|
|
|
|
assert(false);
|
|
|
|
break;
|
|
|
|
}
|
2019-11-06 20:10:56 -05:00
|
|
|
}
|
2019-12-13 23:21:59 -05:00
|
|
|
|
2019-11-06 20:10:56 -05:00
|
|
|
Framework::CMemStream shaderStream;
|
|
|
|
Nuanceur::CSpirvShaderGenerator::Generate(shaderStream, b, Nuanceur::CSpirvShaderGenerator::SHADER_TYPE_COMPUTE);
|
|
|
|
shaderStream.Seek(0, Framework::STREAM_SEEK_SET);
|
2019-11-25 20:35:17 -05:00
|
|
|
return Framework::Vulkan::CShaderModule(m_context->device, shaderStream);
|
2019-11-06 20:10:56 -05:00
|
|
|
}
|
|
|
|
|
2020-02-12 19:41:35 -05:00
|
|
|
Nuanceur::CUintRvalue CTransferHost::XferStream_Read32(Nuanceur::CShaderBuilder& b, Nuanceur::CArrayUintValue xferBuffer, Nuanceur::CIntValue pixelIndex)
|
2019-11-28 20:17:10 -05:00
|
|
|
{
|
|
|
|
return Load(xferBuffer, pixelIndex);
|
|
|
|
}
|
|
|
|
|
2020-02-12 19:41:35 -05:00
|
|
|
Nuanceur::CUintRvalue CTransferHost::XferStream_Read24(Nuanceur::CShaderBuilder& b, Nuanceur::CArrayUintValue xferBuffer, Nuanceur::CIntValue pixelIndex)
|
2020-01-30 12:45:14 -05:00
|
|
|
{
|
|
|
|
auto byteOffset = pixelIndex * NewInt(b, 3);
|
|
|
|
auto byte0 = XferStream_Read8(b, xferBuffer, byteOffset + NewInt(b, 0));
|
|
|
|
auto byte1 = XferStream_Read8(b, xferBuffer, byteOffset + NewInt(b, 1));
|
|
|
|
auto byte2 = XferStream_Read8(b, xferBuffer, byteOffset + NewInt(b, 2));
|
|
|
|
return (byte0) | (byte1 << NewUint(b, 8)) | (byte2 << NewUint(b, 16));
|
|
|
|
}
|
|
|
|
|
2020-02-12 19:41:35 -05:00
|
|
|
Nuanceur::CUintRvalue CTransferHost::XferStream_Read16(Nuanceur::CShaderBuilder& b, Nuanceur::CArrayUintValue xferBuffer, Nuanceur::CIntValue pixelIndex)
|
2019-12-15 12:25:31 -05:00
|
|
|
{
|
2019-12-17 09:19:37 -05:00
|
|
|
auto srcOffset = pixelIndex / NewInt(b, 2);
|
|
|
|
auto srcShift = (ToUint(pixelIndex) & NewUint(b, 1)) * NewUint(b, 16);
|
2019-12-15 12:25:31 -05:00
|
|
|
return (Load(xferBuffer, srcOffset) >> srcShift) & NewUint(b, 0xFFFF);
|
|
|
|
}
|
|
|
|
|
2020-02-12 19:41:35 -05:00
|
|
|
Nuanceur::CUintRvalue CTransferHost::XferStream_Read8(Nuanceur::CShaderBuilder& b, Nuanceur::CArrayUintValue xferBuffer, Nuanceur::CIntValue pixelIndex)
|
2019-11-28 20:17:10 -05:00
|
|
|
{
|
|
|
|
auto srcOffset = pixelIndex / NewInt(b, 4);
|
|
|
|
auto srcShift = (ToUint(pixelIndex) & NewUint(b, 3)) * NewUint(b, 8);
|
|
|
|
return (Load(xferBuffer, srcOffset) >> srcShift) & NewUint(b, 0xFF);
|
|
|
|
}
|
|
|
|
|
2020-02-12 19:41:35 -05:00
|
|
|
Nuanceur::CUintRvalue CTransferHost::XferStream_Read4(Nuanceur::CShaderBuilder& b, Nuanceur::CArrayUintValue xferBuffer, Nuanceur::CIntValue pixelIndex)
|
2020-01-20 13:24:09 -05:00
|
|
|
{
|
|
|
|
auto srcOffset = pixelIndex / NewInt(b, 8);
|
|
|
|
auto srcShift = (ToUint(pixelIndex) & NewUint(b, 7)) * NewUint(b, 4);
|
|
|
|
return (Load(xferBuffer, srcOffset) >> srcShift) & NewUint(b, 0xF);
|
|
|
|
}
|
|
|
|
|
2020-02-12 19:41:35 -05:00
|
|
|
PIPELINE CTransferHost::CreateXferPipeline(const PIPELINE_CAPS& caps)
|
2019-11-06 20:10:56 -05:00
|
|
|
{
|
2019-12-05 18:55:27 -05:00
|
|
|
PIPELINE xferPipeline;
|
2019-11-25 20:35:17 -05:00
|
|
|
|
|
|
|
auto xferShader = CreateXferShader(caps);
|
|
|
|
|
2019-11-06 20:10:56 -05:00
|
|
|
VkResult result = VK_SUCCESS;
|
|
|
|
|
|
|
|
{
|
|
|
|
std::vector<VkDescriptorSetLayoutBinding> bindings;
|
|
|
|
|
|
|
|
//GS memory
|
|
|
|
{
|
|
|
|
VkDescriptorSetLayoutBinding binding = {};
|
2019-12-13 23:21:59 -05:00
|
|
|
binding.binding = DESCRIPTOR_LOCATION_MEMORY;
|
2019-12-17 19:22:27 -05:00
|
|
|
binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
2019-11-06 20:10:56 -05:00
|
|
|
binding.descriptorCount = 1;
|
2019-12-13 23:21:59 -05:00
|
|
|
binding.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
|
2019-11-06 20:10:56 -05:00
|
|
|
bindings.push_back(binding);
|
|
|
|
}
|
2021-04-02 16:45:07 +01:00
|
|
|
|
2021-03-30 22:51:40 +01:00
|
|
|
//GS memory - 8bit buffer access
|
2021-09-24 21:59:21 -04:00
|
|
|
if(TRANSFER_USE_8_16_BIT)
|
2021-03-30 22:51:40 +01:00
|
|
|
{
|
|
|
|
VkDescriptorSetLayoutBinding binding = {};
|
|
|
|
binding.binding = DESCRIPTOR_LOCATION_MEMORY_8BIT;
|
|
|
|
binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
|
|
|
binding.descriptorCount = 1;
|
|
|
|
binding.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
|
|
|
|
bindings.push_back(binding);
|
|
|
|
}
|
2019-11-06 20:10:56 -05:00
|
|
|
|
2021-04-02 16:45:07 +01:00
|
|
|
//GS memory - 16bit buffer access
|
2021-09-24 21:59:21 -04:00
|
|
|
if(TRANSFER_USE_8_16_BIT)
|
2021-04-02 16:45:07 +01:00
|
|
|
{
|
|
|
|
VkDescriptorSetLayoutBinding binding = {};
|
|
|
|
binding.binding = DESCRIPTOR_LOCATION_MEMORY_16BIT;
|
|
|
|
binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
|
|
|
binding.descriptorCount = 1;
|
|
|
|
binding.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
|
|
|
|
bindings.push_back(binding);
|
|
|
|
}
|
|
|
|
|
2019-11-06 20:10:56 -05:00
|
|
|
//Xfer buffer
|
|
|
|
{
|
|
|
|
VkDescriptorSetLayoutBinding binding = {};
|
2019-12-13 23:21:59 -05:00
|
|
|
binding.binding = DESCRIPTOR_LOCATION_XFERBUFFER;
|
2020-01-16 08:41:08 -05:00
|
|
|
binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
|
2019-11-06 20:10:56 -05:00
|
|
|
binding.descriptorCount = 1;
|
2019-12-13 23:21:59 -05:00
|
|
|
binding.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
|
2019-11-06 20:10:56 -05:00
|
|
|
bindings.push_back(binding);
|
|
|
|
}
|
|
|
|
|
2019-12-11 21:34:37 -05:00
|
|
|
//Dst Swizzle Table
|
|
|
|
{
|
|
|
|
VkDescriptorSetLayoutBinding binding = {};
|
2019-12-13 23:21:59 -05:00
|
|
|
binding.binding = DESCRIPTOR_LOCATION_SWIZZLETABLE_DST;
|
|
|
|
binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
2019-12-11 21:34:37 -05:00
|
|
|
binding.descriptorCount = 1;
|
2019-12-13 23:21:59 -05:00
|
|
|
binding.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
|
2019-12-11 21:34:37 -05:00
|
|
|
bindings.push_back(binding);
|
|
|
|
}
|
|
|
|
|
2019-11-06 20:10:56 -05:00
|
|
|
auto createInfo = Framework::Vulkan::DescriptorSetLayoutCreateInfo();
|
|
|
|
createInfo.bindingCount = bindings.size();
|
2019-12-13 23:21:59 -05:00
|
|
|
createInfo.pBindings = bindings.data();
|
2019-11-25 20:35:17 -05:00
|
|
|
result = m_context->device.vkCreateDescriptorSetLayout(m_context->device, &createInfo, nullptr, &xferPipeline.descriptorSetLayout);
|
2019-11-06 20:10:56 -05:00
|
|
|
CHECKVULKANERROR(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
2019-11-15 13:20:14 -05:00
|
|
|
VkPushConstantRange pushConstantInfo = {};
|
|
|
|
pushConstantInfo.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
|
2019-12-13 23:21:59 -05:00
|
|
|
pushConstantInfo.offset = 0;
|
|
|
|
pushConstantInfo.size = sizeof(XFERPARAMS);
|
2019-11-06 20:10:56 -05:00
|
|
|
|
|
|
|
auto pipelineLayoutCreateInfo = Framework::Vulkan::PipelineLayoutCreateInfo();
|
2019-11-15 13:20:14 -05:00
|
|
|
pipelineLayoutCreateInfo.pushConstantRangeCount = 1;
|
2019-12-13 23:21:59 -05:00
|
|
|
pipelineLayoutCreateInfo.pPushConstantRanges = &pushConstantInfo;
|
|
|
|
pipelineLayoutCreateInfo.setLayoutCount = 1;
|
|
|
|
pipelineLayoutCreateInfo.pSetLayouts = &xferPipeline.descriptorSetLayout;
|
2019-11-06 20:10:56 -05:00
|
|
|
|
2019-11-25 20:35:17 -05:00
|
|
|
result = m_context->device.vkCreatePipelineLayout(m_context->device, &pipelineLayoutCreateInfo, nullptr, &xferPipeline.pipelineLayout);
|
2019-11-06 20:10:56 -05:00
|
|
|
CHECKVULKANERROR(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
auto createInfo = Framework::Vulkan::ComputePipelineCreateInfo();
|
|
|
|
createInfo.stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
|
|
|
createInfo.stage.stage = VK_SHADER_STAGE_COMPUTE_BIT;
|
|
|
|
createInfo.stage.pName = "main";
|
2019-11-25 20:35:17 -05:00
|
|
|
createInfo.stage.module = xferShader;
|
|
|
|
createInfo.layout = xferPipeline.pipelineLayout;
|
2019-11-06 20:10:56 -05:00
|
|
|
|
2019-11-25 20:35:17 -05:00
|
|
|
result = m_context->device.vkCreateComputePipelines(m_context->device, VK_NULL_HANDLE, 1, &createInfo, nullptr, &xferPipeline.pipeline);
|
2019-11-06 20:10:56 -05:00
|
|
|
CHECKVULKANERROR(result);
|
|
|
|
}
|
2019-11-25 20:35:17 -05:00
|
|
|
|
|
|
|
return xferPipeline;
|
2019-11-06 20:10:56 -05:00
|
|
|
}
|