2024-04-20 17:29:29 -04:00
// SPDX-FileCopyrightText: 2024 Joshua Goins <josh@redstrate.com>
// SPDX-License-Identifier: GPL-3.0-or-later
# include "rendersystem.h"
# include <array>
# include <QDebug>
# include <physis.hpp>
# include "dxbc_module.h"
# include "dxbc_reader.h"
# include "renderer.hpp"
# include <spirv_glsl.hpp>
2024-04-21 09:01:02 -04:00
# include <glm/ext/matrix_clip_space.hpp>
2024-04-21 11:52:30 -04:00
// TODO: maybe need UV?
2024-04-21 14:12:56 -04:00
// note: SQEX passes the vertice positions as UV coordinates (yes, -1 to 1.) the shaders then transform them back with the g_CommonParameter.m_RenderTarget vec4
2024-04-21 11:52:30 -04:00
const std : : vector < glm : : vec4 > planeVertices = {
2024-04-21 13:04:25 -04:00
{ - 1.0f , - 1.0f , 0.0f , 1.0f } ,
{ 1.0f , - 1.0f , 0.0f , 1.0f } ,
{ 1.0f , 1.0f , 0.0f , 1.0f } ,
2024-04-21 11:52:30 -04:00
2024-04-21 13:04:25 -04:00
{ - 1.0f , 1.0f , 0.0f , 1.0f } ,
{ - 1.0f , - 1.0f , 0.0f , 1.0f } ,
{ 1.0f , 1.0f , 0.0f , 1.0f } ,
2024-04-21 11:52:30 -04:00
} ;
2024-04-20 17:29:29 -04:00
dxvk : : Logger dxvk : : Logger : : s_instance ( " dxbc.log " ) ;
2024-04-21 10:30:51 -04:00
const std : : array < std : : string , 14 > passes = {
2024-04-20 17:29:29 -04:00
// Shadows?
" PASS_0 " ,
2024-04-21 13:04:25 -04:00
// Z "prepass"
2024-04-20 17:29:29 -04:00
" PASS_Z_OPAQUE " ,
2024-04-21 13:04:25 -04:00
// computes and stores normals (TODO: denote how these normals are special)
2024-04-20 17:29:29 -04:00
" PASS_G_OPAQUE " ,
// g run for each light
// takes view pos, then unknown texture and normal
" PASS_LIGHTING_OPAQUE " ,
" PASS_G_SEMITRANSPARENCY " ,
" PASS_COMPOSITE_OPAQUE " ,
" PASS_7 " ,
" PASS_WATER " ,
" PASS_WATER_Z " ,
" PASS_SEMITRANSPARENCY " ,
" PASS_COMPOSITE_SEMITRANSPARENCY " ,
" PASS_10 " ,
" PASS_12 " ,
" PASS_14 " } ;
2024-04-21 10:30:51 -04:00
const int INVALID_PASS = 255 ;
2024-04-20 17:29:29 -04:00
RenderSystem : : RenderSystem ( Renderer & renderer , GameData * data )
: m_renderer ( renderer )
, m_data ( data )
{
2024-04-21 11:52:30 -04:00
size_t vertexSize = planeVertices . size ( ) * sizeof ( glm : : vec4 ) ;
auto [ vertexBuffer , vertexMemory ] = m_renderer . createBuffer ( vertexSize , VK_BUFFER_USAGE_VERTEX_BUFFER_BIT ) ;
m_planeVertexBuffer = vertexBuffer ;
m_planeVertexMemory = vertexMemory ;
// copy vertex data
{
void * mapped_data = nullptr ;
vkMapMemory ( m_renderer . device , vertexMemory , 0 , vertexSize , 0 , & mapped_data ) ;
memcpy ( mapped_data , planeVertices . data ( ) , vertexSize ) ;
VkMappedMemoryRange range = { } ;
range . sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE ;
range . memory = vertexMemory ;
range . size = vertexSize ;
vkFlushMappedMemoryRanges ( m_renderer . device , 1 , & range ) ;
vkUnmapMemory ( m_renderer . device , vertexMemory ) ;
}
2024-04-21 10:25:52 -04:00
directionalLightningShpk = physis_parse_shpk ( physis_gamedata_extract_file ( m_data , " shader/sm5/shpk/directionallighting.shpk " ) ) ;
2024-04-21 13:17:40 -04:00
createViewPositionShpk = physis_parse_shpk ( physis_gamedata_extract_file ( m_data , " shader/sm5/shpk/createviewposition.shpk " ) ) ;
2024-04-21 10:25:52 -04:00
2024-04-21 09:01:02 -04:00
// camera data
{
g_CameraParameter = createUniformBuffer ( sizeof ( CameraParameter ) ) ;
}
// joint matrix data
{
g_JointMatrixArray = createUniformBuffer ( sizeof ( JointMatrixArray ) ) ;
JointMatrixArray jointMatrixArray { } ;
for ( int i = 0 ; i < 64 ; i + + ) {
jointMatrixArray . g_JointMatrixArray [ i ] = glm : : mat3x4 ( 1.0f ) ;
}
copyDataToUniform ( g_JointMatrixArray , & jointMatrixArray , sizeof ( JointMatrixArray ) ) ;
}
// instance data
{
g_InstanceParameter = createUniformBuffer ( sizeof ( InstanceParameter ) ) ;
InstanceParameter instanceParameter { } ;
copyDataToUniform ( g_InstanceParameter , & instanceParameter , sizeof ( InstanceParameter ) ) ;
}
// model data
{
g_ModelParameter = createUniformBuffer ( sizeof ( ModelParameter ) ) ;
ModelParameter modelParameter { } ;
copyDataToUniform ( g_ModelParameter , & modelParameter , sizeof ( ModelParameter ) ) ;
}
// material data
{
g_MaterialParameter = createUniformBuffer ( sizeof ( MaterialParameter ) ) ;
MaterialParameter materialParameter { } ;
materialParameter . g_AlphaThreshold = 0.0f ;
materialParameter . g_DiffuseColor = glm : : vec3 ( 1.0f ) ;
copyDataToUniform ( g_MaterialParameter , & materialParameter , sizeof ( MaterialParameter ) ) ;
}
2024-04-21 13:04:25 -04:00
// light data
{
g_LightParam = createUniformBuffer ( sizeof ( LightParam ) ) ;
LightParam lightParam { } ;
2024-04-21 14:05:41 -04:00
lightParam . m_Position = glm : : vec4 ( - 5 ) ;
2024-04-21 13:04:25 -04:00
lightParam . m_Direction = glm : : normalize ( glm : : vec4 ( 0 ) - lightParam . m_Position ) ;
lightParam . m_DiffuseColor = glm : : vec4 ( 1 ) ;
lightParam . m_SpecularColor = glm : : vec4 ( 1 ) ;
lightParam . m_Attenuation = glm : : vec4 ( 5.0f ) ;
/*lightParam.m_ClipMin = glm::vec4(0.0f);
lightParam . m_ClipMax = glm : : vec4 ( 5.0f ) ; */
copyDataToUniform ( g_LightParam , & lightParam , sizeof ( LightParam ) ) ;
}
// common data
{
g_CommonParameter = createUniformBuffer ( sizeof ( CommonParameter ) ) ;
}
2024-04-21 14:11:40 -04:00
createImageResources ( ) ;
2024-04-20 17:29:29 -04:00
}
void RenderSystem : : testInit ( : : RenderModel * m )
{
2024-04-21 07:02:34 -04:00
RenderModel model { . shpk = physis_parse_shpk ( physis_gamedata_extract_file ( m_data , " shader/sm5/shpk/character.shpk " ) ) ,
. internal_model = new : : RenderModel ( * m ) } ;
2024-04-20 17:29:29 -04:00
m_renderModels . push_back ( model ) ;
}
void RenderSystem : : render ( uint32_t imageIndex , VkCommandBuffer commandBuffer )
{
2024-04-21 09:01:02 -04:00
// TODO: this shouldn't be here
CameraParameter cameraParameter { } ;
2024-04-21 14:11:40 -04:00
glm : : mat4 projectionMatrix = glm : : perspective ( glm : : radians ( 45.0f ) , ( float ) m_extent . width / ( float ) m_extent . height , 0.1f , 1000.0f ) ;
2024-04-21 09:01:02 -04:00
glm : : mat4 viewMatrix = m_renderer . view ;
glm : : mat4 viewProjectionMatrix = projectionMatrix * viewMatrix ;
2024-04-21 13:29:30 -04:00
cameraParameter . m_ViewMatrix = glm : : transpose ( viewMatrix ) ;
cameraParameter . m_InverseViewMatrix = glm : : transpose ( glm : : inverse ( viewMatrix ) ) ;
2024-04-21 09:01:02 -04:00
cameraParameter . m_ViewProjectionMatrix = glm : : transpose ( viewProjectionMatrix ) ;
2024-04-21 13:29:30 -04:00
cameraParameter . m_InverseViewProjectionMatrix = glm : : transpose ( glm : : inverse ( viewProjectionMatrix ) ) ;
2024-04-21 14:05:41 -04:00
// known params
cameraParameter . m_InverseProjectionMatrix = glm : : transpose ( glm : : inverse ( viewProjectionMatrix ) ) ;
cameraParameter . m_ProjectionMatrix = glm : : transpose ( viewProjectionMatrix ) ;
cameraParameter . m_MainViewToProjectionMatrix = glm : : transpose ( glm : : inverse ( projectionMatrix ) ) ;
2024-04-21 09:01:02 -04:00
cameraParameter . m_EyePosition = glm : : vec3 ( 5.0f ) ; // placeholder
2024-04-21 13:29:30 -04:00
cameraParameter . m_LookAtVector = glm : : vec3 ( 0.0f ) ; // placeholder
2024-04-21 09:01:02 -04:00
copyDataToUniform ( g_CameraParameter , & cameraParameter , sizeof ( CameraParameter ) ) ;
2024-04-20 17:29:29 -04:00
int i = 0 ;
for ( const auto pass : passes ) {
// hardcoded to the known pass for now
2024-04-21 13:04:25 -04:00
if ( pass = = " PASS_G_OPAQUE " | | pass = = " PASS_Z_OPAQUE " ) {
2024-04-21 13:17:40 -04:00
beginPass ( imageIndex , commandBuffer , pass ) ;
2024-04-20 17:29:29 -04:00
for ( auto & model : m_renderModels ) {
2024-04-21 10:08:55 -04:00
std : : vector < uint32_t > systemKeys ;
std : : vector < uint32_t > sceneKeys = {
physis_shpk_crc ( " TransformViewSkin " ) ,
physis_shpk_crc ( " GetAmbientLight_SH " ) ,
physis_shpk_crc ( " GetReflectColor_Texture " ) ,
physis_shpk_crc ( " GetAmbientOcclusion_None " ) ,
physis_shpk_crc ( " ApplyDitherClipOff " ) ,
} ;
std : : vector < uint32_t > materialKeys ;
for ( int j = 0 ; j < model . shpk . num_material_keys ; j + + ) {
2024-04-21 11:52:30 -04:00
auto value = model . shpk . material_keys [ j ] . default_value ;
// Replace MODE_DEFAULT with MODE_SIMPLE for now
if ( value ! = 0x5CC605B5 ) {
materialKeys . push_back ( model . shpk . material_keys [ j ] . default_value ) ;
} else {
materialKeys . push_back ( 0x22A4AABF ) ;
}
2024-04-21 10:08:55 -04:00
}
2024-04-21 11:52:30 -04:00
std : : vector < uint32_t > subviewKeys = { physis_shpk_crc ( " Default " ) , physis_shpk_crc ( " SUB_VIEW_MAIN " ) } ;
2024-04-21 10:08:55 -04:00
const u_int32_t selector = physis_shpk_build_selector_from_all_keys ( systemKeys . data ( ) ,
systemKeys . size ( ) ,
sceneKeys . data ( ) ,
sceneKeys . size ( ) ,
materialKeys . data ( ) ,
materialKeys . size ( ) ,
subviewKeys . data ( ) ,
subviewKeys . size ( ) ) ;
2024-04-20 17:29:29 -04:00
const physis_SHPKNode node = physis_shpk_get_node ( & model . shpk , selector ) ;
// check if invalid
if ( node . pass_count = = 0 ) {
continue ;
}
// this is an index into the node's pass array, not to get confused with the global one we always follow.
const int passIndice = node . pass_indices [ i ] ;
2024-04-21 10:30:51 -04:00
if ( passIndice ! = INVALID_PASS ) {
2024-04-20 17:29:29 -04:00
const Pass currentPass = node . passes [ passIndice ] ;
const uint32_t vertexShaderIndice = currentPass . vertex_shader ;
2024-04-21 11:52:30 -04:00
const uint32_t pixelShaderIndice = currentPass . pixel_shader ;
2024-04-20 17:29:29 -04:00
physis_Shader vertexShader = model . shpk . vertex_shaders [ vertexShaderIndice ] ;
physis_Shader pixelShader = model . shpk . pixel_shaders [ pixelShaderIndice ] ;
2024-04-21 11:52:30 -04:00
bindPipeline ( commandBuffer , pass , vertexShader , pixelShader ) ;
2024-04-20 17:29:29 -04:00
for ( const auto & part : model . internal_model - > parts ) {
VkDeviceSize offsets [ ] = { 0 } ;
vkCmdBindVertexBuffers ( commandBuffer , 0 , 1 , & part . vertexBuffer , offsets ) ;
vkCmdBindIndexBuffer ( commandBuffer , part . indexBuffer , 0 , VK_INDEX_TYPE_UINT16 ) ;
vkCmdDrawIndexed ( commandBuffer , part . numIndices , 1 , 0 , 0 , 0 ) ;
}
}
}
2024-04-21 13:17:40 -04:00
endPass ( commandBuffer , pass ) ;
2024-04-21 12:00:13 -04:00
} else if ( pass = = " PASS_LIGHTING_OPAQUE " ) {
2024-04-21 13:17:40 -04:00
// first we need to generate the view positions with createviewpositions
beginPass ( imageIndex , commandBuffer , " PASS_LIGHTING_OPAQUE_VIEWPOSITION " ) ;
{
std : : vector < uint32_t > systemKeys = {
physis_shpk_crc ( " DecodeDepthBuffer_RAWZ " ) ,
} ;
std : : vector < uint32_t > subviewKeys = {
physis_shpk_crc ( " Default " ) ,
physis_shpk_crc ( " SUB_VIEW_MAIN " ) ,
} ;
const u_int32_t selector = physis_shpk_build_selector_from_all_keys ( systemKeys . data ( ) ,
systemKeys . size ( ) ,
nullptr ,
0 ,
nullptr ,
0 ,
subviewKeys . data ( ) ,
subviewKeys . size ( ) ) ;
const physis_SHPKNode node = physis_shpk_get_node ( & createViewPositionShpk , selector ) ;
// check if invalid
if ( node . pass_count = = 0 ) {
continue ;
}
const int passIndice = node . pass_indices [ i ] ;
if ( passIndice ! = INVALID_PASS ) {
const Pass currentPass = node . passes [ passIndice ] ;
const uint32_t vertexShaderIndice = currentPass . vertex_shader ;
const uint32_t pixelShaderIndice = currentPass . pixel_shader ;
physis_Shader vertexShader = createViewPositionShpk . vertex_shaders [ vertexShaderIndice ] ;
physis_Shader pixelShader = createViewPositionShpk . pixel_shaders [ pixelShaderIndice ] ;
bindPipeline ( commandBuffer , " PASS_LIGHTING_OPAQUE_VIEWPOSITION " , vertexShader , pixelShader ) ;
VkDeviceSize offsets [ ] = { 0 } ;
vkCmdBindVertexBuffers ( commandBuffer , 0 , 1 , & m_planeVertexBuffer , offsets ) ;
vkCmdDraw ( commandBuffer , 6 , 1 , 0 , 0 ) ;
}
2024-04-21 10:25:52 -04:00
}
2024-04-21 13:17:40 -04:00
endPass ( commandBuffer , pass ) ;
beginPass ( imageIndex , commandBuffer , pass ) ;
// then run the directionallighting shader
{
std : : vector < uint32_t > systemKeys = {
physis_shpk_crc ( " DecodeDepthBuffer_RAWZ " ) ,
} ;
std : : vector < uint32_t > sceneKeys = {
physis_shpk_crc ( " GetDirectionalLight_Enable " ) ,
physis_shpk_crc ( " GetFakeSpecular_Disable " ) ,
physis_shpk_crc ( " GetUnderWaterLighting_Disable " ) ,
} ;
std : : vector < uint32_t > subviewKeys = {
physis_shpk_crc ( " Default " ) ,
physis_shpk_crc ( " SUB_VIEW_MAIN " ) ,
} ;
const u_int32_t selector = physis_shpk_build_selector_from_all_keys ( systemKeys . data ( ) ,
systemKeys . size ( ) ,
sceneKeys . data ( ) ,
sceneKeys . size ( ) ,
nullptr ,
0 ,
subviewKeys . data ( ) ,
subviewKeys . size ( ) ) ;
const physis_SHPKNode node = physis_shpk_get_node ( & directionalLightningShpk , selector ) ;
// check if invalid
if ( node . pass_count = = 0 ) {
continue ;
}
2024-04-21 10:25:52 -04:00
2024-04-21 13:17:40 -04:00
const int passIndice = node . pass_indices [ i ] ;
if ( passIndice ! = INVALID_PASS ) {
const Pass currentPass = node . passes [ passIndice ] ;
2024-04-21 10:25:52 -04:00
2024-04-21 13:17:40 -04:00
const uint32_t vertexShaderIndice = currentPass . vertex_shader ;
const uint32_t pixelShaderIndice = currentPass . pixel_shader ;
2024-04-21 10:25:52 -04:00
2024-04-21 13:17:40 -04:00
physis_Shader vertexShader = directionalLightningShpk . vertex_shaders [ vertexShaderIndice ] ;
physis_Shader pixelShader = directionalLightningShpk . pixel_shaders [ pixelShaderIndice ] ;
2024-04-21 10:25:52 -04:00
2024-04-21 13:17:40 -04:00
bindPipeline ( commandBuffer , pass , vertexShader , pixelShader ) ;
2024-04-21 11:52:30 -04:00
2024-04-21 13:17:40 -04:00
VkDeviceSize offsets [ ] = { 0 } ;
vkCmdBindVertexBuffers ( commandBuffer , 0 , 1 , & m_planeVertexBuffer , offsets ) ;
2024-04-21 11:52:30 -04:00
2024-04-21 13:17:40 -04:00
vkCmdDraw ( commandBuffer , 6 , 1 , 0 , 0 ) ;
}
2024-04-21 10:25:52 -04:00
}
2024-04-21 13:17:40 -04:00
endPass ( commandBuffer , pass ) ;
2024-04-20 17:29:29 -04:00
}
i + + ;
}
}
void RenderSystem : : setSize ( uint32_t width , uint32_t height )
{
m_extent = { width , height } ;
2024-04-21 13:17:40 -04:00
// TODO: this is because of our terrible resource handling. an image referenced in these may be gone due to resizing, for example
for ( auto & [ hash , cachedPipeline ] : m_cachedPipelines ) {
cachedPipeline . cachedDescriptors . clear ( ) ;
}
2024-04-21 14:11:40 -04:00
createImageResources ( ) ;
2024-04-20 17:29:29 -04:00
}
void RenderSystem : : beginPass ( uint32_t imageIndex , VkCommandBuffer commandBuffer , const std : : string_view passName )
{
2024-04-21 11:52:30 -04:00
VkRenderingInfo renderingInfo { VK_STRUCTURE_TYPE_RENDERING_INFO } ;
2024-04-20 17:29:29 -04:00
renderingInfo . renderArea . extent = m_extent ;
std : : vector < VkRenderingAttachmentInfo > colorAttachments ;
VkRenderingAttachmentInfo depthStencilAttachment { } ;
if ( passName = = " PASS_G_OPAQUE " ) {
// normals, it seems like
{
VkRenderingAttachmentInfo attachmentInfo { VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO } ;
2024-04-21 12:00:13 -04:00
attachmentInfo . imageView = normalGBuffer . imageView ;
2024-04-21 11:52:30 -04:00
attachmentInfo . imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ; // VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
2024-04-20 17:29:29 -04:00
attachmentInfo . loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR ;
attachmentInfo . storeOp = VK_ATTACHMENT_STORE_OP_STORE ;
attachmentInfo . clearValue . color . float32 [ 0 ] = 0.24 ;
attachmentInfo . clearValue . color . float32 [ 1 ] = 0.24 ;
attachmentInfo . clearValue . color . float32 [ 2 ] = 0.24 ;
attachmentInfo . clearValue . color . float32 [ 3 ] = 1.0 ;
colorAttachments . push_back ( attachmentInfo ) ;
}
// unknown, seems to be background?
{
VkRenderingAttachmentInfo attachmentInfo { VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO } ;
attachmentInfo . imageView = VK_NULL_HANDLE ;
attachmentInfo . imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ;
attachmentInfo . loadOp = VK_ATTACHMENT_LOAD_OP_LOAD ;
attachmentInfo . storeOp = VK_ATTACHMENT_STORE_OP_STORE ;
colorAttachments . push_back ( attachmentInfo ) ;
}
// unknown, seems to be background?
{
VkRenderingAttachmentInfo attachmentInfo { VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO } ;
attachmentInfo . imageView = VK_NULL_HANDLE ;
attachmentInfo . imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ;
attachmentInfo . loadOp = VK_ATTACHMENT_LOAD_OP_LOAD ;
attachmentInfo . storeOp = VK_ATTACHMENT_STORE_OP_STORE ;
colorAttachments . push_back ( attachmentInfo ) ;
}
// depth
{
VkRenderingAttachmentInfo attachmentInfo { VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO } ;
attachmentInfo . imageView = m_renderer . depthView ;
attachmentInfo . imageLayout = VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL ;
attachmentInfo . loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR ;
attachmentInfo . storeOp = VK_ATTACHMENT_STORE_OP_STORE ;
attachmentInfo . clearValue . depthStencil . depth = 1.0f ;
depthStencilAttachment = attachmentInfo ;
}
2024-04-21 11:52:30 -04:00
} else if ( passName = = " PASS_LIGHTING_OPAQUE " ) {
// normals, it seems like
{
VkRenderingAttachmentInfo attachmentInfo { VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO } ;
attachmentInfo . imageView = m_renderer . swapchainViews [ imageIndex ] ;
attachmentInfo . imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ; // VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
attachmentInfo . loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR ;
attachmentInfo . storeOp = VK_ATTACHMENT_STORE_OP_STORE ;
attachmentInfo . clearValue . color . float32 [ 0 ] = 0.24 ;
attachmentInfo . clearValue . color . float32 [ 1 ] = 0.24 ;
attachmentInfo . clearValue . color . float32 [ 2 ] = 0.24 ;
attachmentInfo . clearValue . color . float32 [ 3 ] = 1.0 ;
colorAttachments . push_back ( attachmentInfo ) ;
}
// unknown
{
VkRenderingAttachmentInfo attachmentInfo { VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO } ;
attachmentInfo . imageView = VK_NULL_HANDLE ;
attachmentInfo . imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ;
attachmentInfo . loadOp = VK_ATTACHMENT_LOAD_OP_LOAD ;
attachmentInfo . storeOp = VK_ATTACHMENT_STORE_OP_STORE ;
2024-04-21 13:17:40 -04:00
colorAttachments . push_back ( attachmentInfo ) ;
}
} else if ( passName = = " PASS_LIGHTING_OPAQUE_VIEWPOSITION " ) {
// TODO: Hack we should not be using a special pass for this, we should just design our API better
{
VkRenderingAttachmentInfo attachmentInfo { VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO } ;
attachmentInfo . imageView = viewPositionBuffer . imageView ;
attachmentInfo . imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ; // VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
attachmentInfo . loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR ;
attachmentInfo . storeOp = VK_ATTACHMENT_STORE_OP_STORE ;
attachmentInfo . clearValue . color . float32 [ 0 ] = 0.24 ;
attachmentInfo . clearValue . color . float32 [ 1 ] = 0.24 ;
attachmentInfo . clearValue . color . float32 [ 2 ] = 0.24 ;
attachmentInfo . clearValue . color . float32 [ 3 ] = 1.0 ;
2024-04-21 11:52:30 -04:00
colorAttachments . push_back ( attachmentInfo ) ;
}
2024-04-21 13:04:25 -04:00
} else if ( passName = = " PASS_Z_OPAQUE " ) {
// normals, it seems like
{
VkRenderingAttachmentInfo attachmentInfo { VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO } ;
attachmentInfo . imageView = m_renderer . swapchainViews [ imageIndex ] ;
attachmentInfo . imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ; // VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
attachmentInfo . loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR ;
attachmentInfo . storeOp = VK_ATTACHMENT_STORE_OP_STORE ;
attachmentInfo . clearValue . color . float32 [ 0 ] = 0.24 ;
attachmentInfo . clearValue . color . float32 [ 1 ] = 0.24 ;
attachmentInfo . clearValue . color . float32 [ 2 ] = 0.24 ;
attachmentInfo . clearValue . color . float32 [ 3 ] = 1.0 ;
colorAttachments . push_back ( attachmentInfo ) ;
}
// unknown
{
VkRenderingAttachmentInfo attachmentInfo { VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO } ;
attachmentInfo . imageView = VK_NULL_HANDLE ;
attachmentInfo . imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ;
attachmentInfo . loadOp = VK_ATTACHMENT_LOAD_OP_LOAD ;
attachmentInfo . storeOp = VK_ATTACHMENT_STORE_OP_STORE ;
colorAttachments . push_back ( attachmentInfo ) ;
}
2024-04-20 17:29:29 -04:00
}
renderingInfo . layerCount = 1 ;
renderingInfo . pColorAttachments = colorAttachments . data ( ) ;
renderingInfo . colorAttachmentCount = colorAttachments . size ( ) ;
if ( depthStencilAttachment . imageView ! = VK_NULL_HANDLE ) {
renderingInfo . pDepthAttachment = & depthStencilAttachment ;
}
vkCmdBeginRendering ( commandBuffer , & renderingInfo ) ;
}
2024-04-21 11:52:30 -04:00
void RenderSystem : : endPass ( VkCommandBuffer commandBuffer , std : : string_view passName )
2024-04-20 17:29:29 -04:00
{
vkCmdEndRendering ( commandBuffer ) ;
}
2024-04-21 11:52:30 -04:00
void RenderSystem : : bindPipeline ( VkCommandBuffer commandBuffer , std : : string_view passName , physis_Shader & vertexShader , physis_Shader & pixelShader )
2024-04-20 17:29:29 -04:00
{
2024-04-21 11:52:30 -04:00
const uint32_t hash = vertexShader . len + pixelShader . len + physis_shpk_crc ( passName . data ( ) ) ;
2024-04-20 17:29:29 -04:00
if ( ! m_cachedPipelines . contains ( hash ) ) {
auto vertexShaderModule = convertShaderModule ( vertexShader , spv : : ExecutionModelVertex ) ;
auto fragmentShaderModule = convertShaderModule ( pixelShader , spv : : ExecutionModelFragment ) ;
VkPipelineShaderStageCreateInfo vertexShaderStageInfo = { } ;
vertexShaderStageInfo . sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO ;
vertexShaderStageInfo . stage = VK_SHADER_STAGE_VERTEX_BIT ;
vertexShaderStageInfo . module = vertexShaderModule ;
vertexShaderStageInfo . pName = " main " ;
VkPipelineShaderStageCreateInfo fragmentShaderStageInfo = { } ;
fragmentShaderStageInfo . sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO ;
fragmentShaderStageInfo . stage = VK_SHADER_STAGE_FRAGMENT_BIT ;
2024-04-21 11:52:30 -04:00
fragmentShaderStageInfo . module = fragmentShaderModule ; // m_renderer.loadShaderFromDisk(":/shaders/dummy.frag.spv");
2024-04-20 17:29:29 -04:00
fragmentShaderStageInfo . pName = " main " ;
std : : array < VkPipelineShaderStageCreateInfo , 2 > shaderStages = { vertexShaderStageInfo , fragmentShaderStageInfo } ;
VkVertexInputBindingDescription binding = { } ;
2024-04-21 11:52:30 -04:00
// TODO: temporary
2024-04-21 13:04:25 -04:00
if ( passName = = " PASS_G_OPAQUE " | | passName = = " PASS_Z_OPAQUE " ) {
2024-04-21 11:52:30 -04:00
binding . stride = sizeof ( Vertex ) ;
2024-04-21 13:17:40 -04:00
} else if ( passName = = " PASS_LIGHTING_OPAQUE " | | passName = = " PASS_LIGHTING_OPAQUE_VIEWPOSITION " ) {
2024-04-21 11:52:30 -04:00
binding . stride = sizeof ( glm : : vec4 ) ;
}
2024-04-20 17:29:29 -04:00
auto vertex_glsl = getShaderModuleResources ( vertexShader ) ;
auto vertex_resources = vertex_glsl . get_shader_resources ( ) ;
auto fragment_glsl = getShaderModuleResources ( pixelShader ) ;
auto fragment_resources = fragment_glsl . get_shader_resources ( ) ;
std : : vector < RequestedSet > requestedSets ;
const auto & collectResources = [ & requestedSets ] ( const spirv_cross : : CompilerGLSL & glsl ,
const spirv_cross : : SmallVector < spirv_cross : : Resource > & resources ,
const VkShaderStageFlagBits stageFlagBit ) {
for ( auto resource : resources ) {
unsigned set = glsl . get_decoration ( resource . id , spv : : DecorationDescriptorSet ) ;
unsigned binding = glsl . get_decoration ( resource . id , spv : : DecorationBinding ) ;
if ( requestedSets . size ( ) < = set ) {
requestedSets . resize ( set + 1 ) ;
}
auto & requestSet = requestedSets [ set ] ;
requestSet . used = true ;
if ( requestSet . bindings . size ( ) < = binding ) {
requestSet . bindings . resize ( binding + 1 ) ;
}
auto type = glsl . get_type ( resource . type_id ) ;
if ( type . basetype = = spirv_cross : : SPIRType : : Image ) {
requestSet . bindings [ binding ] . type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ;
} else if ( type . basetype = = spirv_cross : : SPIRType : : Struct ) {
requestSet . bindings [ binding ] . type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ;
} else if ( type . basetype = = spirv_cross : : SPIRType : : Sampler ) {
requestSet . bindings [ binding ] . type = VK_DESCRIPTOR_TYPE_SAMPLER ;
}
requestSet . bindings [ binding ] . used = true ;
requestSet . bindings [ binding ] . stageFlags | = stageFlagBit ;
qInfo ( ) < < " Requesting set " < < set < < " at " < < binding ;
}
} ;
collectResources ( vertex_glsl , vertex_resources . uniform_buffers , VK_SHADER_STAGE_VERTEX_BIT ) ;
collectResources ( vertex_glsl , vertex_resources . separate_images , VK_SHADER_STAGE_VERTEX_BIT ) ;
collectResources ( vertex_glsl , vertex_resources . separate_samplers , VK_SHADER_STAGE_VERTEX_BIT ) ;
collectResources ( fragment_glsl , fragment_resources . uniform_buffers , VK_SHADER_STAGE_FRAGMENT_BIT ) ;
collectResources ( fragment_glsl , fragment_resources . separate_images , VK_SHADER_STAGE_FRAGMENT_BIT ) ;
collectResources ( fragment_glsl , fragment_resources . separate_samplers , VK_SHADER_STAGE_FRAGMENT_BIT ) ;
for ( auto & set : requestedSets ) {
if ( set . used ) {
int j = 0 ;
std : : vector < VkDescriptorSetLayoutBinding > bindings ;
for ( auto & binding : set . bindings ) {
if ( binding . used ) {
VkDescriptorSetLayoutBinding boneInfoBufferBinding = { } ;
boneInfoBufferBinding . descriptorType = binding . type ;
boneInfoBufferBinding . descriptorCount = 1 ;
boneInfoBufferBinding . stageFlags = binding . stageFlags ;
boneInfoBufferBinding . binding = j ;
bindings . push_back ( boneInfoBufferBinding ) ;
}
j + + ;
}
VkDescriptorSetLayoutCreateInfo layoutInfo = { } ;
layoutInfo . sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO ;
layoutInfo . bindingCount = bindings . size ( ) ;
layoutInfo . pBindings = bindings . data ( ) ;
vkCreateDescriptorSetLayout ( m_renderer . device , & layoutInfo , nullptr , & set . layout ) ;
}
}
std : : vector < VkVertexInputAttributeDescription > attributeDescs ;
for ( auto texture : vertex_resources . stage_inputs ) {
unsigned binding = vertex_glsl . get_decoration ( texture . id , spv : : DecorationLocation ) ;
2024-04-21 09:01:02 -04:00
auto name = vertex_glsl . get_name ( texture . id ) ;
2024-04-20 17:29:29 -04:00
VkVertexInputAttributeDescription uv0Attribute = { } ;
auto type = vertex_glsl . get_type ( texture . type_id ) ;
if ( type . basetype = = spirv_cross : : SPIRType : : Int ) {
switch ( type . vecsize ) {
case 1 :
uv0Attribute . format = VK_FORMAT_R32_SINT ;
break ;
case 2 :
uv0Attribute . format = VK_FORMAT_R32G32_SINT ;
break ;
case 3 :
uv0Attribute . format = VK_FORMAT_R32G32B32_SINT ;
break ;
case 4 :
2024-04-21 09:01:02 -04:00
uv0Attribute . format = VK_FORMAT_R8G8B8A8_UINT ; // supposed to be VK_FORMAT_R32G32B32A32_SINT, but our bone_id is uint8_t currently
2024-04-20 17:29:29 -04:00
break ;
}
} else {
switch ( type . vecsize ) {
case 1 :
uv0Attribute . format = VK_FORMAT_R32_SFLOAT ;
break ;
case 2 :
uv0Attribute . format = VK_FORMAT_R32G32_SFLOAT ;
break ;
case 3 :
uv0Attribute . format = VK_FORMAT_R32G32B32_SFLOAT ;
break ;
case 4 :
uv0Attribute . format = VK_FORMAT_R32G32B32A32_SFLOAT ;
break ;
}
}
uv0Attribute . location = binding ;
2024-04-21 09:01:02 -04:00
// TODO: temporary
if ( name = = " v0 " ) {
uv0Attribute . offset = offsetof ( Vertex , position ) ;
} else if ( name = = " v1 " ) {
uv0Attribute . offset = offsetof ( Vertex , color ) ;
} else if ( name = = " v2 " ) {
uv0Attribute . offset = offsetof ( Vertex , normal ) ;
} else if ( name = = " v3 " ) {
uv0Attribute . offset = offsetof ( Vertex , uv0 ) ;
} else if ( name = = " v4 " ) {
uv0Attribute . offset = offsetof ( Vertex , bitangent ) ; // FIXME: should be tangent
} else if ( name = = " v5 " ) {
uv0Attribute . offset = offsetof ( Vertex , bitangent ) ;
} else if ( name = = " v6 " ) {
uv0Attribute . offset = offsetof ( Vertex , bone_weight ) ;
} else if ( name = = " v7 " ) {
uv0Attribute . offset = offsetof ( Vertex , bone_id ) ;
}
2024-04-20 17:29:29 -04:00
attributeDescs . push_back ( uv0Attribute ) ;
}
VkPipelineVertexInputStateCreateInfo vertexInputState = { } ;
vertexInputState . sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO ;
vertexInputState . vertexBindingDescriptionCount = 1 ;
vertexInputState . pVertexBindingDescriptions = & binding ;
vertexInputState . vertexAttributeDescriptionCount = attributeDescs . size ( ) ;
vertexInputState . pVertexAttributeDescriptions = attributeDescs . data ( ) ;
VkPipelineInputAssemblyStateCreateInfo inputAssembly = { } ;
inputAssembly . sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO ;
inputAssembly . topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST ;
VkPipelineViewportStateCreateInfo viewportState = { } ;
viewportState . sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO ;
viewportState . viewportCount = 1 ;
viewportState . scissorCount = 1 ;
VkPipelineRasterizationStateCreateInfo rasterizer = { } ;
rasterizer . sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO ;
rasterizer . lineWidth = 1.0f ;
2024-04-21 13:04:25 -04:00
rasterizer . cullMode = VK_CULL_MODE_NONE ; // TODO: implement cull mode
2024-04-20 17:29:29 -04:00
rasterizer . frontFace = VK_FRONT_FACE_CLOCKWISE ;
VkPipelineMultisampleStateCreateInfo multisampling = { } ;
multisampling . sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO ;
multisampling . rasterizationSamples = VK_SAMPLE_COUNT_1_BIT ;
VkPipelineColorBlendAttachmentState colorBlendAttachment = { } ;
colorBlendAttachment . colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT ;
2024-04-21 11:52:30 -04:00
std : : vector < VkPipelineColorBlendAttachmentState > colorBlendAttachments ;
int colorAttachmentCount = 1 ;
// TODO: hardcoded, should be a reusable function to get the color attachments
if ( passName = = " PASS_G_OPAQUE " ) {
colorAttachmentCount = 3 ;
} else if ( passName = = " PASS_LIGHTING_OPAQUE " ) {
colorAttachmentCount = 2 ;
}
for ( int i = 0 ; i < colorAttachmentCount ; i + + ) {
colorBlendAttachments . push_back ( colorBlendAttachment ) ;
}
2024-04-20 17:29:29 -04:00
VkPipelineColorBlendStateCreateInfo colorBlending = { } ;
colorBlending . sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO ;
colorBlending . attachmentCount = colorBlendAttachments . size ( ) ;
colorBlending . pAttachments = colorBlendAttachments . data ( ) ;
2024-04-21 14:11:40 -04:00
std : : vector < VkDynamicState > dynamicStates = { VK_DYNAMIC_STATE_VIEWPORT , VK_DYNAMIC_STATE_SCISSOR } ;
2024-04-20 17:29:29 -04:00
VkPipelineDynamicStateCreateInfo dynamicState = { } ;
dynamicState . sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO ;
2024-04-21 14:11:40 -04:00
dynamicState . dynamicStateCount = dynamicStates . size ( ) ;
dynamicState . pDynamicStates = dynamicStates . data ( ) ;
2024-04-20 17:29:29 -04:00
VkPipelineLayoutCreateInfo pipelineLayoutInfo { } ;
pipelineLayoutInfo . sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO ;
// pipelineLayoutInfo.pushConstantRangeCount = 1;
// pipelineLayoutInfo.pPushConstantRanges = &pushConstantRange;
std : : vector < VkDescriptorSetLayout > setLayouts ;
for ( auto & set : requestedSets ) {
if ( set . used ) {
setLayouts . push_back ( set . layout ) ;
}
}
pipelineLayoutInfo . setLayoutCount = setLayouts . size ( ) ;
pipelineLayoutInfo . pSetLayouts = setLayouts . data ( ) ;
VkPipelineLayout pipelineLayout = VK_NULL_HANDLE ;
vkCreatePipelineLayout ( m_renderer . device , & pipelineLayoutInfo , nullptr , & pipelineLayout ) ;
VkPipelineDepthStencilStateCreateInfo depthStencil = { } ;
depthStencil . sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO ;
depthStencil . depthTestEnable = VK_TRUE ;
depthStencil . depthWriteEnable = VK_TRUE ;
depthStencil . depthCompareOp = VK_COMPARE_OP_LESS ;
depthStencil . maxDepthBounds = 1.0f ;
std : : array < VkFormat , 3 > colorAttachmentFormats = { VK_FORMAT_B8G8R8A8_UNORM , VK_FORMAT_UNDEFINED , VK_FORMAT_UNDEFINED } ;
VkPipelineRenderingCreateInfo pipelineRenderingCreateInfo = { } ;
pipelineRenderingCreateInfo . sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO ;
pipelineRenderingCreateInfo . colorAttachmentCount = 3 ; // TODO: hardcoded
pipelineRenderingCreateInfo . pColorAttachmentFormats = colorAttachmentFormats . data ( ) ;
pipelineRenderingCreateInfo . depthAttachmentFormat = VK_FORMAT_D32_SFLOAT ; // TODO: hardcoded
VkGraphicsPipelineCreateInfo createInfo = { } ;
createInfo . pNext = & pipelineRenderingCreateInfo ;
createInfo . sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO ;
createInfo . stageCount = shaderStages . size ( ) ;
createInfo . pStages = shaderStages . data ( ) ;
createInfo . pVertexInputState = & vertexInputState ;
createInfo . pInputAssemblyState = & inputAssembly ;
createInfo . pViewportState = & viewportState ;
createInfo . pRasterizationState = & rasterizer ;
createInfo . pMultisampleState = & multisampling ;
createInfo . pColorBlendState = & colorBlending ;
createInfo . pDynamicState = & dynamicState ;
createInfo . pDepthStencilState = & depthStencil ;
createInfo . layout = pipelineLayout ;
// createInfo.renderPass = m_renderer.renderPass;
VkPipeline pipeline = VK_NULL_HANDLE ;
vkCreateGraphicsPipelines ( m_renderer . device , VK_NULL_HANDLE , 1 , & createInfo , nullptr , & pipeline ) ;
qInfo ( ) < < " Created " < < pipeline < < " for hash " < < hash ;
2024-04-21 09:01:02 -04:00
m_cachedPipelines [ hash ] = CachedPipeline { . pipeline = pipeline ,
. pipelineLayout = pipelineLayout ,
. setLayouts = setLayouts ,
. requestedSets = requestedSets ,
. vertexShader = vertexShader ,
. pixelShader = pixelShader } ;
2024-04-20 17:29:29 -04:00
}
auto & pipeline = m_cachedPipelines [ hash ] ;
vkCmdBindPipeline ( commandBuffer , VK_PIPELINE_BIND_POINT_GRAPHICS , pipeline . pipeline ) ; // TODO: return CachedPipeline&
2024-04-21 11:52:30 -04:00
int i = 0 ;
for ( auto setLayout : pipeline . setLayouts ) {
if ( ! pipeline . cachedDescriptors . count ( i ) ) {
if ( auto descriptor = createDescriptorFor ( pipeline , i ) ; descriptor ! = VK_NULL_HANDLE ) {
pipeline . cachedDescriptors [ i ] = descriptor ;
} else {
continue ;
}
}
// TODO: we can pass all descriptors in one function call
vkCmdBindDescriptorSets ( commandBuffer , VK_PIPELINE_BIND_POINT_GRAPHICS , pipeline . pipelineLayout , i , 1 , & pipeline . cachedDescriptors [ i ] , 0 , nullptr ) ;
i + + ;
}
2024-04-21 14:11:40 -04:00
VkViewport viewport = { } ;
viewport . width = m_extent . width ;
viewport . height = m_extent . height ;
viewport . maxDepth = 1.0f ;
VkRect2D scissor = { } ;
scissor . extent = m_extent ;
vkCmdSetViewport ( commandBuffer , 0 , 1 , & viewport ) ;
vkCmdSetScissor ( commandBuffer , 0 , 1 , & scissor ) ;
2024-04-20 17:29:29 -04:00
}
VkShaderModule RenderSystem : : convertShaderModule ( const physis_Shader & shader , spv : : ExecutionModel executionModel )
{
dxvk : : DxbcReader reader ( reinterpret_cast < const char * > ( shader . bytecode ) , shader . len ) ;
dxvk : : DxbcModule module ( reader ) ;
dxvk : : DxbcModuleInfo info ;
auto result = module . compile ( info , " test " ) ;
VkShaderModuleCreateInfo createInfo = { } ;
createInfo . sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO ;
createInfo . codeSize = result . code . size ( ) ;
createInfo . pCode = reinterpret_cast < const uint32_t * > ( result . code . data ( ) ) ;
VkShaderModule shaderModule ;
vkCreateShaderModule ( m_renderer . device , & createInfo , nullptr , & shaderModule ) ;
2024-04-21 09:01:02 -04:00
// TODO: for debug only
spirv_cross : : CompilerGLSL glsl ( result . code . data ( ) , result . code . dwords ( ) ) ;
auto resources = glsl . get_shader_resources ( ) ;
int i = 0 ;
for ( auto texture : resources . stage_inputs ) {
// glsl.set_name(texture.id, shader.)
// qInfo() << shader.resource_parameters[i].name << texture.id;
// qInfo() << "stage input" << i << texture.name << glsl.get_type(texture.type_id).width;
i + + ;
// glsl.set_name(remap.combined_id, "SPIRV_Cross_Combined");
}
// Here you can also set up decorations if you want (binding = #N).
i = 0 ;
for ( auto texture : resources . separate_images ) {
glsl . set_name ( texture . id , shader . resource_parameters [ i ] . name ) ;
i + + ;
}
i = 0 ;
for ( auto buffer : resources . uniform_buffers ) {
glsl . set_name ( buffer . id , shader . scalar_parameters [ i ] . name ) ;
i + + ;
}
spirv_cross : : CompilerGLSL : : Options options ;
options . vulkan_semantics = true ;
options . enable_420pack_extension = false ;
glsl . set_common_options ( options ) ;
glsl . set_entry_point ( " main " , executionModel ) ;
qInfo ( ) < < " Compiled GLSL: " < < glsl . compile ( ) . c_str ( ) ;
2024-04-20 17:29:29 -04:00
return shaderModule ;
}
spirv_cross : : CompilerGLSL RenderSystem : : getShaderModuleResources ( const physis_Shader & shader )
{
dxvk : : DxbcReader reader ( reinterpret_cast < const char * > ( shader . bytecode ) , shader . len ) ;
dxvk : : DxbcModule module ( reader ) ;
dxvk : : DxbcModuleInfo info ;
auto result = module . compile ( info , " test " ) ;
// glsl.build_combined_image_samplers();
return spirv_cross : : CompilerGLSL ( result . code . data ( ) , result . code . dwords ( ) ) ;
}
2024-04-21 11:52:30 -04:00
VkDescriptorSet RenderSystem : : createDescriptorFor ( const CachedPipeline & pipeline , int i )
2024-04-20 17:29:29 -04:00
{
VkDescriptorSet set ;
VkDescriptorSetAllocateInfo allocateInfo = { } ;
allocateInfo . sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO ;
allocateInfo . descriptorPool = m_renderer . descriptorPool ;
allocateInfo . descriptorSetCount = 1 ;
allocateInfo . pSetLayouts = & pipeline . setLayouts [ i ] ;
vkAllocateDescriptorSets ( m_renderer . device , & allocateInfo , & set ) ;
if ( set = = VK_NULL_HANDLE ) {
// qFatal("Failed to create descriptor set!");
return VK_NULL_HANDLE ;
}
// TODO: way too eager
std : : vector < VkWriteDescriptorSet > writes ;
std : : vector < VkDescriptorBufferInfo > bufferInfo ;
std : : vector < VkDescriptorImageInfo > imageInfo ;
writes . reserve ( pipeline . requestedSets [ i ] . bindings . size ( ) ) ;
bufferInfo . reserve ( pipeline . requestedSets [ i ] . bindings . size ( ) ) ;
imageInfo . reserve ( pipeline . requestedSets [ i ] . bindings . size ( ) ) ;
int j = 0 ;
2024-04-21 09:01:02 -04:00
int z = 0 ;
2024-04-21 13:04:25 -04:00
int p = 0 ;
VkShaderStageFlags currentStageFlags ;
2024-04-20 17:29:29 -04:00
for ( auto binding : pipeline . requestedSets [ i ] . bindings ) {
if ( binding . used ) {
2024-04-21 13:04:25 -04:00
// a giant hack
if ( currentStageFlags ! = binding . stageFlags ) {
z = 0 ;
p = 0 ;
currentStageFlags = binding . stageFlags ;
}
2024-04-20 17:29:29 -04:00
VkWriteDescriptorSet & descriptorWrite = writes . emplace_back ( ) ;
descriptorWrite . sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET ;
descriptorWrite . descriptorType = binding . type ;
descriptorWrite . dstSet = set ;
descriptorWrite . descriptorCount = 1 ;
descriptorWrite . dstBinding = j ;
switch ( binding . type ) {
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE : {
auto info = & imageInfo . emplace_back ( ) ;
descriptorWrite . pImageInfo = info ;
2024-04-21 13:04:25 -04:00
if ( binding . stageFlags = = VK_SHADER_STAGE_FRAGMENT_BIT & & p < 4 ) {
auto name = pipeline . pixelShader . resource_parameters [ p ] . name ;
qInfo ( ) < < " Requesting image " < < name < < " at " < < j ;
if ( strcmp ( name , " g_SamplerGBuffer " ) = = 0 ) {
info - > imageView = normalGBuffer . imageView ;
} else if ( strcmp ( name , " g_SamplerViewPosition " ) = = 0 ) {
2024-04-21 13:17:40 -04:00
info - > imageView = viewPositionBuffer . imageView ;
} else if ( strcmp ( name , " g_SamplerDepth " ) = = 0 ) {
info - > imageView = m_renderer . depthView ;
2024-04-21 13:04:25 -04:00
} else {
info - > imageView = m_renderer . dummyView ;
}
p + + ;
} else {
info - > imageView = m_renderer . dummyView ;
}
2024-04-20 17:29:29 -04:00
info - > imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ;
} break ;
case VK_DESCRIPTOR_TYPE_SAMPLER : {
auto info = & imageInfo . emplace_back ( ) ;
descriptorWrite . pImageInfo = info ;
info - > sampler = m_renderer . dummySampler ;
} break ;
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER : {
auto info = & bufferInfo . emplace_back ( ) ;
descriptorWrite . pBufferInfo = info ;
2024-04-21 09:01:02 -04:00
auto useUniformBuffer = [ & info ] ( UniformBuffer & buffer ) {
info - > buffer = buffer . buffer ;
info - > range = buffer . size ;
} ;
2024-04-21 13:04:25 -04:00
auto bindBuffer = [ this , & useUniformBuffer , & info , j ] ( const char * name ) {
2024-04-21 09:01:02 -04:00
qInfo ( ) < < " Requesting " < < name < < " at " < < j ;
if ( strcmp ( name , " g_CameraParameter " ) = = 0 ) {
useUniformBuffer ( g_CameraParameter ) ;
} else if ( strcmp ( name , " g_JointMatrixArray " ) = = 0 ) {
useUniformBuffer ( g_JointMatrixArray ) ;
} else if ( strcmp ( name , " g_InstanceParameter " ) = = 0 ) {
useUniformBuffer ( g_InstanceParameter ) ;
} else if ( strcmp ( name , " g_ModelParameter " ) = = 0 ) {
useUniformBuffer ( g_ModelParameter ) ;
2024-04-21 13:04:25 -04:00
} else if ( strcmp ( name , " g_MaterialParameter " ) = = 0 ) {
useUniformBuffer ( g_MaterialParameter ) ;
} else if ( strcmp ( name , " g_LightParam " ) = = 0 ) {
useUniformBuffer ( g_LightParam ) ;
} else if ( strcmp ( name , " g_CommonParameter " ) = = 0 ) {
useUniformBuffer ( g_CommonParameter ) ;
2024-04-21 09:01:02 -04:00
} else {
qInfo ( ) < < " Unknown resource: " < < name ;
info - > buffer = m_renderer . dummyBuffer ;
info - > range = 655360 ;
}
2024-04-21 13:04:25 -04:00
} ;
if ( binding . stageFlags = = VK_SHADER_STAGE_VERTEX_BIT ) {
auto name = pipeline . vertexShader . scalar_parameters [ z ] . name ;
bindBuffer ( name ) ;
z + + ;
} else if ( binding . stageFlags = = VK_SHADER_STAGE_FRAGMENT_BIT ) {
auto name = pipeline . pixelShader . scalar_parameters [ z ] . name ;
2024-04-21 09:01:02 -04:00
2024-04-21 13:04:25 -04:00
bindBuffer ( name ) ;
2024-04-21 09:01:02 -04:00
z + + ;
} else {
// placeholder buffer so it at least doesn't crash
info - > buffer = m_renderer . dummyBuffer ;
info - > range = 655360 ;
}
2024-04-20 17:29:29 -04:00
} break ;
}
}
j + + ;
}
vkUpdateDescriptorSets ( m_renderer . device , writes . size ( ) , writes . data ( ) , 0 , nullptr ) ;
return set ;
2024-04-21 09:01:02 -04:00
}
RenderSystem : : UniformBuffer RenderSystem : : createUniformBuffer ( size_t size )
{
UniformBuffer uniformBuffer { } ;
uniformBuffer . size = size ;
VkBufferCreateInfo bufferInfo = { } ;
bufferInfo . sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO ;
bufferInfo . size = size ;
bufferInfo . usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT ;
bufferInfo . sharingMode = VK_SHARING_MODE_EXCLUSIVE ;
vkCreateBuffer ( m_renderer . device , & bufferInfo , nullptr , & uniformBuffer . buffer ) ;
// allocate staging memory
VkMemoryRequirements memRequirements ;
vkGetBufferMemoryRequirements ( m_renderer . device , uniformBuffer . buffer , & memRequirements ) ;
VkMemoryAllocateInfo allocInfo = { } ;
allocInfo . sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO ;
allocInfo . allocationSize = memRequirements . size ;
allocInfo . memoryTypeIndex =
m_renderer . findMemoryType ( memRequirements . memoryTypeBits , VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT ) ;
vkAllocateMemory ( m_renderer . device , & allocInfo , nullptr , & uniformBuffer . memory ) ;
vkBindBufferMemory ( m_renderer . device , uniformBuffer . buffer , uniformBuffer . memory , 0 ) ;
return uniformBuffer ;
}
void RenderSystem : : copyDataToUniform ( RenderSystem : : UniformBuffer & uniformBuffer , void * data , size_t size )
{
// copy to staging buffer
void * mapped_data ;
vkMapMemory ( m_renderer . device , uniformBuffer . memory , 0 , size , 0 , & mapped_data ) ;
memcpy ( mapped_data , data , size ) ;
vkUnmapMemory ( m_renderer . device , uniformBuffer . memory ) ;
}
2024-04-21 12:00:13 -04:00
RenderSystem : : VulkanImage RenderSystem : : createImage ( int width , int height , VkFormat format , VkImageUsageFlags usage )
{
VkImage image ;
VkImageView imageView ;
VkDeviceMemory imageMemory ;
VkImageCreateInfo imageCreateInfo = { } ;
imageCreateInfo . sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO ;
imageCreateInfo . imageType = VK_IMAGE_TYPE_2D ;
imageCreateInfo . extent . width = width ;
imageCreateInfo . extent . height = height ;
imageCreateInfo . extent . depth = 1 ;
imageCreateInfo . mipLevels = 1 ;
imageCreateInfo . arrayLayers = 1 ;
imageCreateInfo . format = format ;
imageCreateInfo . tiling = VK_IMAGE_TILING_OPTIMAL ;
imageCreateInfo . initialLayout = VK_IMAGE_LAYOUT_UNDEFINED ;
imageCreateInfo . usage = usage ;
imageCreateInfo . samples = VK_SAMPLE_COUNT_1_BIT ;
imageCreateInfo . sharingMode = VK_SHARING_MODE_EXCLUSIVE ;
vkCreateImage ( m_renderer . device , & imageCreateInfo , nullptr , & image ) ;
VkMemoryRequirements memRequirements ;
vkGetImageMemoryRequirements ( m_renderer . device , image , & memRequirements ) ;
VkMemoryAllocateInfo allocateInfo = { } ;
allocateInfo . sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO ;
allocateInfo . allocationSize = memRequirements . size ;
allocateInfo . memoryTypeIndex = m_renderer . findMemoryType ( memRequirements . memoryTypeBits , VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT ) ;
vkAllocateMemory ( m_renderer . device , & allocateInfo , nullptr , & imageMemory ) ;
vkBindImageMemory ( m_renderer . device , image , imageMemory , 0 ) ;
VkImageViewCreateInfo viewCreateInfo = { } ;
viewCreateInfo . sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO ;
viewCreateInfo . image = image ;
viewCreateInfo . viewType = VK_IMAGE_VIEW_TYPE_2D ;
viewCreateInfo . format = format ;
viewCreateInfo . subresourceRange . aspectMask = VK_IMAGE_ASPECT_COLOR_BIT ; // TODO: hardcoded
viewCreateInfo . subresourceRange . levelCount = 1 ;
viewCreateInfo . subresourceRange . layerCount = 1 ;
vkCreateImageView ( m_renderer . device , & viewCreateInfo , nullptr , & imageView ) ;
return { image , imageView , imageMemory } ;
}
2024-04-21 14:11:40 -04:00
void RenderSystem : : createImageResources ( )
{
normalGBuffer = createImage ( m_extent . width , m_extent . height , VK_FORMAT_R8G8B8A8_UNORM , VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ) ;
viewPositionBuffer = createImage ( m_extent . width , m_extent . height , VK_FORMAT_R8G8B8A8_UNORM , VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ) ;
CommonParameter commonParam { } ;
/*commonParam.m_RenderTarget = {1640.0f / 2.0f,
480.0f / 2.0f ,
640.0f / 2.0 ,
480.0f / 2.0 } ; // used to convert screen-space coordinates back into 0.0-1.0
*/
commonParam . m_RenderTarget = { 1.0f / m_extent . width , 1.0f / m_extent . height , 0.0f , 0.0f } ; // used to convert screen-space coordinates back into 0.0-1.0
copyDataToUniform ( g_CommonParameter , & commonParam , sizeof ( CommonParameter ) ) ;
}