@@ -1283,7 +1283,24 @@ PF_Err SmartRender(
12831283 InputImageInfo.sharingMode = vk::SharingMode::eExclusive;
12841284 InputImageInfo.initialLayout = vk::ImageLayout::eUndefined;
12851285
1286- if ( InputImageInfo == SequenceParam->Cache .InputImageInfoCache )
1286+ // Get "hash" of current input image
1287+ const A_Time CurTime = {in_data->current_time , in_data->time_scale };
1288+ const A_Time CurTimeStep = {in_data->time_step , in_data->time_scale };
1289+
1290+ PF_State CurState = {};
1291+ ERR (suites.ParamUtilsSuite3 ()->PF_GetCurrentState (
1292+ in_data->effect_ref , Vulkanator::ParamID::Input, &CurTime, &CurTimeStep,
1293+ &CurState
1294+ ));
1295+
1296+ // Compare hash of the currently uploaded texture against the cached one
1297+ A_Boolean InputImageStateIsSame = false ;
1298+ ERR (suites.ParamUtilsSuite3 ()->PF_AreStatesIdentical (
1299+ in_data->effect_ref , &SequenceParam->Cache .InputImageState , &CurState,
1300+ &InputImageStateIsSame
1301+ ));
1302+
1303+ if ( InputImageStateIsSame )
12871304 {
12881305 // Cache Hit
12891306 }
@@ -1300,19 +1317,21 @@ PF_Err SmartRender(
13001317 )
13011318 .value ();
13021319 SequenceParam->Cache .InputImageInfoCache = InputImageInfo;
1320+ SequenceParam->Cache .InputImageState = CurState;
13031321 }
13041322
1305- // This provides a mapping between the image contents and the staging buffer
1323+ // This provides a mapping between the image contents and the staging
1324+ // buffer
13061325 const vk::BufferImageCopy InputBufferMapping (
13071326 0 , std::uint32_t (InputLayer->rowbytes / PixelSize), 0 ,
13081327 vk::ImageSubresourceLayers (vk::ImageAspectFlagBits::eColor, 0 , 0 , 1 ),
13091328 vk::Offset3D (0 , 0 , 0 ),
13101329 vk::Extent3D (InputLayer->width , InputLayer->height , 1 )
13111330 );
13121331
1313- // Input image view, this is used to create an interpretation of a certain
1314- // aspect of the image This allows things like having a 2D image array but
1315- // creating a view around just one of the images
1332+ // Input image view, this is used to create an interpretation of a
1333+ // certain aspect of the image This allows things like having a 2D image
1334+ // array but creating a view around just one of the images
13161335 vk::ImageViewCreateInfo InputImageViewInfo = {};
13171336 // The target image we are making a view of
13181337 InputImageViewInfo.image = SequenceParam->Cache .InputImage .get ();
@@ -1324,8 +1343,8 @@ PF_Err SmartRender(
13241343 InputImageViewInfo.components .b = vk::ComponentSwizzle::eIdentity;
13251344 InputImageViewInfo.components .a = vk::ComponentSwizzle::eIdentity;
13261345 InputImageViewInfo.subresourceRange = vk::ImageSubresourceRange (
1327- vk::ImageAspectFlagBits::eColor, // We want the "Color" aspect of the
1328- // image
1346+ vk::ImageAspectFlagBits::eColor, // We want the "Color" aspect of
1347+ // the image
13291348 0 , 1 , // A single mipmap, mipmap 0
13301349 0 , 1 // A single image layer, layer 0
13311350 );
@@ -1356,11 +1375,12 @@ PF_Err SmartRender(
13561375 OutputImageInfo.samples = vk::SampleCountFlagBits::e1 ;
13571376 OutputImageInfo.tiling = vk::ImageTiling::eOptimal;
13581377 OutputImageInfo.usage
1359- = vk::ImageUsageFlagBits::eTransferSrc // Will be transferring from this
1360- // image into the staging buffer
1361- | vk::ImageUsageFlagBits::eColorAttachment; // Will be rendering into
1362- // this image within a
1363- // render pass
1378+ = vk::ImageUsageFlagBits::eTransferSrc // Will be transferring from
1379+ // this image into the
1380+ // staging buffer
1381+ | vk::ImageUsageFlagBits::eColorAttachment; // Will be rendering
1382+ // into this image
1383+ // within a render pass
13641384 OutputImageInfo.sharingMode = vk::SharingMode::eExclusive;
13651385 OutputImageInfo.initialLayout = vk::ImageLayout::eUndefined;
13661386
@@ -1383,17 +1403,18 @@ PF_Err SmartRender(
13831403 SequenceParam->Cache .OutputImageInfoCache = OutputImageInfo;
13841404 }
13851405
1386- // This provides a mapping between the image contents and the staging buffer
1406+ // This provides a mapping between the image contents and the staging
1407+ // buffer
13871408 const vk::BufferImageCopy OutputBufferMapping (
13881409 0 , std::uint32_t (OutputLayer->rowbytes / PixelSize), 0 ,
13891410 vk::ImageSubresourceLayers (vk::ImageAspectFlagBits::eColor, 0 , 0 , 1 ),
13901411 vk::Offset3D (0 , 0 , 0 ),
13911412 vk::Extent3D (OutputLayer->width , OutputLayer->height , 1 )
13921413 );
13931414
1394- // Output image view, this is used to create an interpretation of a certain
1395- // aspect of the image This allows things like having a 2D image array but
1396- // creating a view around just one of the images
1415+ // Output image view, this is used to create an interpretation of a
1416+ // certain aspect of the image This allows things like having a 2D image
1417+ // array but creating a view around just one of the images
13971418 vk::ImageViewCreateInfo OutputImageViewInfo = {};
13981419 // The target image we are making a view of
13991420 OutputImageViewInfo.image = SequenceParam->Cache .OutputImage .get ();
@@ -1405,8 +1426,8 @@ PF_Err SmartRender(
14051426 OutputImageViewInfo.components .b = vk::ComponentSwizzle::eIdentity;
14061427 OutputImageViewInfo.components .a = vk::ComponentSwizzle::eIdentity;
14071428 OutputImageViewInfo.subresourceRange = vk::ImageSubresourceRange (
1408- vk::ImageAspectFlagBits::eColor, // We want the "Color" aspect of the
1409- // image
1429+ vk::ImageAspectFlagBits::eColor, // We want the "Color" aspect of
1430+ // the image
14101431 0 , 1 , // A single mipmap, mipmap 0
14111432 0 , 1 // A single image layer, layer 0
14121433 );
@@ -1462,10 +1483,10 @@ PF_Err SmartRender(
14621483 }
14631484
14641485 // Write combined image+sampler object into the descriptor set
1465- // Here, we combine both the sampler and the image, and we state the format
1466- // that the image will be in by the time this sampler will be in-use, which
1467- // is ideally "shader read only optimal" immediately after we are done
1468- // uploading the texture to the GPU
1486+ // Here, we combine both the sampler and the image, and we state the
1487+ // format that the image will be in by the time this sampler will be
1488+ // in-use, which is ideally "shader read only optimal" immediately after
1489+ // we are done uploading the texture to the GPU
14691490 vk::DescriptorImageInfo InputImageSamplerWrite (
14701491 FrameParam->InputImageSampler .get (), InputImageView.get (),
14711492 vk::ImageLayout::eShaderReadOnlyOptimal
@@ -1485,14 +1506,14 @@ PF_Err SmartRender(
14851506 {}
14861507 );
14871508
1488- // Create Render pass Framebuffer, this maps the Output buffer as a color
1489- // attachment for a Renderpass to render into You can add more attachments
1490- // of different formats, but they must all have the same width,height,layers
1491- // Framebuffers will define the image data that render passes will be able
1492- // to address in total
1509+ // Create Render pass Framebuffer, this maps the Output buffer as a
1510+ // color attachment for a Renderpass to render into You can add more
1511+ // attachments of different formats, but they must all have the same
1512+ // width,height,layers Framebuffers will define the image data that
1513+ // render passes will be able to address in total
14931514 vk::FramebufferCreateInfo OutputFramebufferInfo = {};
1494- // This is for the framebuffer to know what ~~~compatible~~~ renderpasses
1495- // will be rendered into it
1515+ // This is for the framebuffer to know what ~~~compatible~~~
1516+ // renderpasses will be rendered into it
14961517 // https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#renderpass-compatibility
14971518 OutputFramebufferInfo.renderPass
14981519 = GlobalParam->RenderPasses [FrameParam->Uniforms .Depth ].get ();
@@ -1518,8 +1539,8 @@ PF_Err SmartRender(
15181539 return PF_Err_INTERNAL_STRUCT_DAMAGED;
15191540 }
15201541
1521- // Copy Input image data into staging buffer, but keep it mapped, as we will
1522- // read the output image data from it later too
1542+ // Copy Input image data into staging buffer, but keep it mapped, as we
1543+ // will read the output image data from it later too
15231544 void * StagingBufferMapping = nullptr ;
15241545
15251546 if ( auto MapResult = GlobalParam->Device ->mapMemory (
@@ -1535,12 +1556,16 @@ PF_Err SmartRender(
15351556 return PF_Err_INTERNAL_STRUCT_DAMAGED;
15361557 }
15371558
1538- // Copy into staging buffer
1539- std::memcpy (
1540- StagingBufferMapping, InputLayer->data ,
1541- InputLayer->rowbytes * InputLayer->height
1542- );
1559+ if ( !InputImageStateIsSame )
1560+ {
1561+ // Copy Input Image into staging buffer
1562+ std::memcpy (
1563+ StagingBufferMapping, InputLayer->data ,
1564+ InputLayer->rowbytes * InputLayer->height
1565+ );
1566+ }
15431567
1568+ // Upload uniform data
15441569 if ( auto MapResult = GlobalParam->Device ->mapMemory (
15451570 SequenceParam->UniformBufferMemory .get (), 0 , VK_WHOLE_SIZE
15461571 );
@@ -1581,58 +1606,69 @@ PF_Err SmartRender(
15811606 {
15821607 // //// Upload staging buffer into Input Image
15831608
1584- // Layout transitions, prepare to copy
1585- // Transfer buffers into images
1586- Cmd.pipelineBarrier (
1587- vk::PipelineStageFlagBits::eHost,
1588- vk::PipelineStageFlagBits::eTransfer, vk::DependencyFlags (), {},
1589- {// Get staging buffer ready for a read
1590- vk::BufferMemoryBarrier (
1591- vk::AccessFlags (), vk::AccessFlagBits::eTransferRead,
1592- VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,
1593- SequenceParam->Cache .StagingBuffer .get (), 0u , VK_WHOLE_SIZE
1594- )},
1595- {
1596- // Get Input Image ready to be written to
1597- vk::ImageMemoryBarrier (
1598- vk::AccessFlags (), vk::AccessFlagBits::eTransferWrite,
1599- vk::ImageLayout::eUndefined,
1600- vk::ImageLayout::eTransferDstOptimal,
1601- VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,
1602- SequenceParam->Cache .InputImage .get (),
1603- vk::ImageSubresourceRange (
1604- vk::ImageAspectFlagBits::eColor, 0 , 1 , 0 , 1
1605- )
1606- ),
1607- }
1608- );
1609+ if ( !InputImageStateIsSame )
1610+ {
1611+ // Layout transitions, prepare to copy
1612+ // Transfer buffers into images
1613+ Cmd.pipelineBarrier (
1614+ vk::PipelineStageFlagBits::eHost,
1615+ vk::PipelineStageFlagBits::eTransfer, vk::DependencyFlags (), {},
1616+ {// Get staging buffer ready for a read
1617+ vk::BufferMemoryBarrier (
1618+ vk::AccessFlags (), vk::AccessFlagBits::eTransferRead,
1619+ VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,
1620+ SequenceParam->Cache .StagingBuffer .get (), 0u , VK_WHOLE_SIZE
1621+ )},
1622+ {
1623+ // Get Input Image ready to be written to
1624+ vk::ImageMemoryBarrier (
1625+ vk::AccessFlags (), vk::AccessFlagBits::eTransferWrite,
1626+ vk::ImageLayout::eUndefined,
1627+ vk::ImageLayout::eTransferDstOptimal,
1628+ VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,
1629+ SequenceParam->Cache .InputImage .get (),
1630+ vk::ImageSubresourceRange (
1631+ vk::ImageAspectFlagBits::eColor, 0 , 1 , 0 , 1
1632+ )
1633+ ),
1634+ }
1635+ );
16091636
1610- // Upload input image data from staging buffer into Input Image
1611- Cmd.copyBufferToImage (
1612- SequenceParam->Cache .StagingBuffer .get (),
1613- SequenceParam->Cache .InputImage .get (),
1614- vk::ImageLayout::eTransferDstOptimal, {InputBufferMapping}
1615- );
1637+ // Upload input image data from staging buffer into Input Image
1638+ Cmd.copyBufferToImage (
1639+ SequenceParam->Cache .StagingBuffer .get (),
1640+ SequenceParam->Cache .InputImage .get (),
1641+ vk::ImageLayout::eTransferDstOptimal, {InputBufferMapping}
1642+ );
16161643
1617- // Layout transitions, copy is complete, ready input image to be sampled
1618- // from
1644+ // Layout transitions, copy is complete, ready input image to be
1645+ // sampled from
1646+ Cmd.pipelineBarrier (
1647+ vk::PipelineStageFlagBits::eTransfer,
1648+ vk::PipelineStageFlagBits::eComputeShader,
1649+ vk::DependencyFlags (), {}, {},
1650+ {// Input Image is going to be read
1651+ vk::ImageMemoryBarrier (
1652+ vk::AccessFlagBits::eTransferWrite,
1653+ vk::AccessFlagBits::eShaderRead,
1654+ vk::ImageLayout::eTransferDstOptimal,
1655+ vk::ImageLayout::eShaderReadOnlyOptimal,
1656+ VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,
1657+ SequenceParam->Cache .InputImage .get (),
1658+ vk::ImageSubresourceRange (
1659+ vk::ImageAspectFlagBits::eColor, 0 , 1 , 0 , 1
1660+ )
1661+ )}
1662+ );
1663+ }
1664+
1665+ // Layout transitions, copy is complete, ready input image to be
1666+ // sampled from
16191667 Cmd.pipelineBarrier (
16201668 vk::PipelineStageFlagBits::eTransfer,
16211669 vk::PipelineStageFlagBits::eComputeShader, vk::DependencyFlags (),
16221670 {}, {},
1623- {// Input Image is going to be read
1624- vk::ImageMemoryBarrier (
1625- vk::AccessFlagBits::eTransferWrite,
1626- vk::AccessFlagBits::eShaderRead,
1627- vk::ImageLayout::eTransferDstOptimal,
1628- vk::ImageLayout::eShaderReadOnlyOptimal,
1629- VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED,
1630- SequenceParam->Cache .InputImage .get (),
1631- vk::ImageSubresourceRange (
1632- vk::ImageAspectFlagBits::eColor, 0 , 1 , 0 , 1
1633- )
1634- ),
1635- // Output Image is going to be written to as a color attachment
1671+ {// Output Image is going to be written to as a color attachment
16361672 // within a render pass
16371673 vk::ImageMemoryBarrier (
16381674 vk::AccessFlags (), vk::AccessFlagBits::eShaderWrite,
@@ -1658,10 +1694,10 @@ PF_Err SmartRender(
16581694 BeginInfo.framebuffer = OutputFramebuffer.get ();
16591695
16601696 // Rectangular region of the output buffer to render into
1661- // TODO: we could potentially have a cached layer-sized output image,
1662- // and only render into a subset of this image using extent_hint if we
1663- // wanted to. But we use the exact output size for more immediate memory
1664- // savings
1697+ // TODO: we could potentially have a cached layer-sized output
1698+ // image, and only render into a subset of this image using
1699+ // extent_hint if we wanted to. But we use the exact output size for
1700+ // more immediate memory savings
16651701 BeginInfo.renderArea .offset .x = BeginInfo.renderArea .offset .y = 0 ;
16661702 BeginInfo.renderArea .extent .width = std::uint32_t (OutputLayer->width );
16671703 BeginInfo.renderArea .extent .height = std::uint32_t (OutputLayer->height );
0 commit comments