#include <string>
#include <vector>
-// \todo Check bufferImageGranularity
+// \todo [2016-03-09 mika] Check bufferImageGranularity
using tcu::TestLog;
using tcu::Maybe;
USAGE_UNIFORM_TEXEL_BUFFER = (0x1u<<8),
USAGE_STORAGE_TEXEL_BUFFER = (0x1u<<9),
- // \todo This is probably almost impossible to do
+ // \todo [2016-03-09 mika] This is probably almost impossible to do
USAGE_INDIRECT_BUFFER = (0x1u<<10),
// Texture usage flags
{
const deUint8* data = (const deUint8*)data_;
- // \todo Optimize
+ // \todo [2016-03-09 mika] Optimize
for (size_t pos = 0; pos < size; pos++)
{
m_data[offset + pos] = data[pos];
void ReferenceMemory::setUndefined (size_t offset, size_t size)
{
- // \todo Optimize
+ // \todo [2016-03-09 mika] Optimize
for (size_t pos = 0; pos < size; pos++)
m_defined[(offset + pos) / 64] |= 0x1ull << ((offset + pos) % 64);
}
vk::VkDeviceSize bestW = de::max(maxTexelCount, maxTextureSize);
vk::VkDeviceSize bestH = maxTexelCount / bestW;
- // \todo Could probably be faster?
+ // \todo [2016-03-09 mika] Could probably be faster?
for (vk::VkDeviceSize w = 1; w * w < maxTexelCount && w < maxTextureSize && bestW * bestH * 4 < size; w++)
{
const vk::VkDeviceSize h = maxTexelCount / w;
DE_ASSERT((size % 4) == 0);
- // \todo Could probably be faster?
+ // \todo [2016-03-09 mika] Could probably be faster?
for (vk::VkDeviceSize w = 1; w < maxTextureSize && w < texelCount; w++)
{
const vk::VkDeviceSize h = texelCount / w;
vk::VkImage getImage (void) const { return m_context.getImage(); }
deInt32 getImageWidth (void) const { return m_context.getImageWidth(); }
deInt32 getImageHeight (void) const { return m_context.getImageHeight(); }
- vk::VkImageLayout getImageLayout (void) const { return m_context.getImageLayout(); }
private:
const PrepareContext& m_context;
TYPE_IMAGE,
TYPE_LAST
};
- PipelineBarrier (const vk::VkPipelineStageFlags srcStages,
- const vk::VkAccessFlags srcAccesses,
- const vk::VkPipelineStageFlags dstStages,
- const vk::VkAccessFlags dstAccesses,
- Type type);
+ PipelineBarrier (const vk::VkPipelineStageFlags srcStages,
+ const vk::VkAccessFlags srcAccesses,
+ const vk::VkPipelineStageFlags dstStages,
+ const vk::VkAccessFlags dstAccesses,
+ Type type,
+ const tcu::Maybe<vk::VkImageLayout> imageLayout);
~PipelineBarrier (void) {}
const char* getName (void) const { return "PipelineBarrier"; }
void submit (SubmitContext& context);
private:
- const vk::VkPipelineStageFlags m_srcStages;
- const vk::VkAccessFlags m_srcAccesses;
- const vk::VkPipelineStageFlags m_dstStages;
- const vk::VkAccessFlags m_dstAccesses;
- const Type m_type;
+ const vk::VkPipelineStageFlags m_srcStages;
+ const vk::VkAccessFlags m_srcAccesses;
+ const vk::VkPipelineStageFlags m_dstStages;
+ const vk::VkAccessFlags m_dstAccesses;
+ const Type m_type;
+ const tcu::Maybe<vk::VkImageLayout> m_imageLayout;
};
-PipelineBarrier::PipelineBarrier (const vk::VkPipelineStageFlags srcStages,
- const vk::VkAccessFlags srcAccesses,
- const vk::VkPipelineStageFlags dstStages,
- const vk::VkAccessFlags dstAccesses,
- Type type)
+PipelineBarrier::PipelineBarrier (const vk::VkPipelineStageFlags srcStages,
+ const vk::VkAccessFlags srcAccesses,
+ const vk::VkPipelineStageFlags dstStages,
+ const vk::VkAccessFlags dstAccesses,
+ Type type,
+ const tcu::Maybe<vk::VkImageLayout> imageLayout)
: m_srcStages (srcStages)
, m_srcAccesses (srcAccesses)
, m_dstStages (dstStages)
, m_dstAccesses (dstAccesses)
, m_type (type)
+ , m_imageLayout (imageLayout)
{
}
m_srcAccesses,
m_dstAccesses,
- context.getImageLayout(),
- context.getImageLayout(),
+ *m_imageLayout,
+ *m_imageLayout,
vk::VK_QUEUE_FAMILY_IGNORED,
vk::VK_QUEUE_FAMILY_IGNORED,
class ImageTransition : public CmdCommand
{
public:
- ImageTransition (void) {}
+ ImageTransition (vk::VkPipelineStageFlags srcStages,
+ vk::VkAccessFlags srcAccesses,
+
+ vk::VkPipelineStageFlags dstStages,
+ vk::VkAccessFlags dstAccesses,
+
+ vk::VkImageLayout srcLayout,
+ vk::VkImageLayout dstLayout);
+
~ImageTransition (void) {}
const char* getName (void) const { return "ImageTransition"; }
void verify (VerifyContext& context, size_t);
private:
- vk::VkDeviceSize m_imageMemorySize;
+ const vk::VkPipelineStageFlags m_srcStages;
+ const vk::VkAccessFlags m_srcAccesses;
+ const vk::VkPipelineStageFlags m_dstStages;
+ const vk::VkAccessFlags m_dstAccesses;
+ const vk::VkImageLayout m_srcLayout;
+ const vk::VkImageLayout m_dstLayout;
+
+ vk::VkDeviceSize m_imageMemorySize;
};
+ImageTransition::ImageTransition (vk::VkPipelineStageFlags srcStages,
+ vk::VkAccessFlags srcAccesses,
+
+ vk::VkPipelineStageFlags dstStages,
+ vk::VkAccessFlags dstAccesses,
+
+ vk::VkImageLayout srcLayout,
+ vk::VkImageLayout dstLayout)
+ : m_srcStages (srcStages)
+ , m_srcAccesses (srcAccesses)
+ , m_dstStages (dstStages)
+ , m_dstAccesses (dstAccesses)
+ , m_srcLayout (srcLayout)
+ , m_dstLayout (dstLayout)
+{
+}
+
void ImageTransition::logSubmit (TestLog& log, size_t commandIndex) const
{
- log << TestLog::Message << commandIndex << ":" << getName() << " Use pipeline barrier to transition to VK_IMAGE_LAYOUT_GENERAL." << TestLog::EndMessage;
+ log << TestLog::Message << commandIndex << ":" << getName()
+ << " Image transition pipeline barrier"
+ << ", srcStages: " << vk::getPipelineStageFlagsStr(m_srcStages) << ", srcAccesses: " << vk::getAccessFlagsStr(m_srcAccesses)
+ << ", dstStages: " << vk::getPipelineStageFlagsStr(m_dstStages) << ", dstAccesses: " << vk::getAccessFlagsStr(m_dstAccesses)
+ << ", srcLayout: " << m_srcLayout << ", dstLayout: " << m_dstLayout << TestLog::EndMessage;
}
void ImageTransition::prepare (PrepareContext& context)
{
- context.setImageLayout(vk::VK_IMAGE_LAYOUT_GENERAL);
+ DE_ASSERT(context.getImageLayout() == vk::VK_IMAGE_LAYOUT_UNDEFINED || m_srcLayout == vk::VK_IMAGE_LAYOUT_UNDEFINED || context.getImageLayout() == m_srcLayout);
+
+ context.setImageLayout(m_dstLayout);
m_imageMemorySize = context.getImageMemorySize();
}
vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
DE_NULL,
- ALL_ACCESSES,
- ALL_ACCESSES,
+ m_srcAccesses,
+ m_dstAccesses,
- context.getImageLayout(),
- vk::VK_IMAGE_LAYOUT_GENERAL,
+ m_srcLayout,
+ m_dstLayout,
vk::VK_QUEUE_FAMILY_IGNORED,
vk::VK_QUEUE_FAMILY_IGNORED,
}
};
- vkd.cmdPipelineBarrier(cmd, ALL_PIPELINE_STAGES, ALL_PIPELINE_STAGES, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &barrier);
+ vkd.cmdPipelineBarrier(cmd, m_srcStages, m_dstStages, (vk::VkDependencyFlags)0, 0, (const vk::VkMemoryBarrier*)DE_NULL, 0, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1, &barrier);
}
void ImageTransition::verify (VerifyContext& context, size_t)
class ImageCopyToBuffer : public CmdCommand
{
public:
- ImageCopyToBuffer (void) {}
+ ImageCopyToBuffer (vk::VkImageLayout imageLayout) : m_imageLayout (imageLayout) {}
~ImageCopyToBuffer (void) {}
const char* getName (void) const { return "BufferCopyToImage"; }
void verify (VerifyContext& context, size_t commandIndex);
private:
+ vk::VkImageLayout m_imageLayout;
vk::VkDeviceSize m_bufferSize;
vk::Move<vk::VkBuffer> m_dstBuffer;
vk::Move<vk::VkDeviceMemory> m_memory;
}
};
- vkd.cmdCopyImageToBuffer(commandBuffer, context.getImage(), context.getImageLayout(), *m_dstBuffer, 1, ®ion);
+ vkd.cmdCopyImageToBuffer(commandBuffer, context.getImage(), m_imageLayout, *m_dstBuffer, 1, ®ion);
}
void ImageCopyToBuffer::verify (VerifyContext& context, size_t commandIndex)
class ImageCopyFromBuffer : public CmdCommand
{
public:
- ImageCopyFromBuffer (deUint32 seed) : m_seed(seed) {}
+ ImageCopyFromBuffer (deUint32 seed, vk::VkImageLayout imageLayout) : m_seed(seed), m_imageLayout(imageLayout) {}
~ImageCopyFromBuffer (void) {}
const char* getName (void) const { return "ImageCopyFromBuffer"; }
private:
const deUint32 m_seed;
+ const vk::VkImageLayout m_imageLayout;
deInt32 m_imageWidth;
deInt32 m_imageHeight;
vk::VkDeviceSize m_imageMemorySize;
}
};
- vkd.cmdCopyBufferToImage(commandBuffer, *m_srcBuffer, context.getImage(), context.getImageLayout(), 1, ®ion);
+ vkd.cmdCopyBufferToImage(commandBuffer, *m_srcBuffer, context.getImage(), m_imageLayout, 1, ®ion);
}
void ImageCopyFromBuffer::verify (VerifyContext& context, size_t)
class ImageCopyFromImage : public CmdCommand
{
public:
- ImageCopyFromImage (deUint32 seed) : m_seed(seed) {}
+ ImageCopyFromImage (deUint32 seed, vk::VkImageLayout imageLayout) : m_seed(seed), m_imageLayout(imageLayout) {}
~ImageCopyFromImage (void) {}
const char* getName (void) const { return "ImageCopyFromImage"; }
private:
const deUint32 m_seed;
+ const vk::VkImageLayout m_imageLayout;
deInt32 m_imageWidth;
deInt32 m_imageHeight;
vk::VkDeviceSize m_imageMemorySize;
}
};
- vkd.cmdCopyImage(commandBuffer, *m_srcImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, context.getImage(), context.getImageLayout(), 1, ®ion);
+ vkd.cmdCopyImage(commandBuffer, *m_srcImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, context.getImage(), m_imageLayout, 1, ®ion);
}
void ImageCopyFromImage::verify (VerifyContext& context, size_t)
class ImageCopyToImage : public CmdCommand
{
public:
- ImageCopyToImage (void) {}
+ ImageCopyToImage (vk::VkImageLayout imageLayout) : m_imageLayout(imageLayout) {}
~ImageCopyToImage (void) {}
const char* getName (void) const { return "ImageCopyToImage"; }
void verify (VerifyContext& context, size_t commandIndex);
private:
+ const vk::VkImageLayout m_imageLayout;
deInt32 m_imageWidth;
deInt32 m_imageHeight;
vk::VkDeviceSize m_imageMemorySize;
}
};
- vkd.cmdCopyImage(commandBuffer, context.getImage(), context.getImageLayout(), *m_dstImage, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
+ vkd.cmdCopyImage(commandBuffer, context.getImage(), m_imageLayout, *m_dstImage, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
}
void ImageCopyToImage::verify (VerifyContext& context, size_t commandIndex)
class ImageBlitFromImage : public CmdCommand
{
public:
- ImageBlitFromImage (deUint32 seed, BlitScale scale) : m_seed(seed), m_scale(scale) {}
+ ImageBlitFromImage (deUint32 seed, BlitScale scale, vk::VkImageLayout imageLayout) : m_seed(seed), m_scale(scale), m_imageLayout(imageLayout) {}
~ImageBlitFromImage (void) {}
const char* getName (void) const { return "ImageBlitFromImage"; }
private:
const deUint32 m_seed;
const BlitScale m_scale;
+ const vk::VkImageLayout m_imageLayout;
deInt32 m_imageWidth;
deInt32 m_imageHeight;
vk::VkDeviceSize m_imageMemorySize;
}
}
};
- vkd.cmdBlitImage(commandBuffer, *m_srcImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, context.getImage(), context.getImageLayout(), 1, ®ion, vk::VK_FILTER_NEAREST);
+ vkd.cmdBlitImage(commandBuffer, *m_srcImage, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, context.getImage(), m_imageLayout, 1, ®ion, vk::VK_FILTER_NEAREST);
}
void ImageBlitFromImage::verify (VerifyContext& context, size_t)
class ImageBlitToImage : public CmdCommand
{
public:
- ImageBlitToImage (BlitScale scale) : m_scale(scale) {}
+ ImageBlitToImage (BlitScale scale, vk::VkImageLayout imageLayout) : m_scale(scale), m_imageLayout(imageLayout) {}
~ImageBlitToImage (void) {}
const char* getName (void) const { return "ImageBlitToImage"; }
private:
const BlitScale m_scale;
+ const vk::VkImageLayout m_imageLayout;
deInt32 m_imageWidth;
deInt32 m_imageHeight;
vk::VkDeviceSize m_imageMemorySize;
}
}
};
- vkd.cmdBlitImage(commandBuffer, context.getImage(), context.getImageLayout(), *m_dstImage, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion, vk::VK_FILTER_NEAREST);
+ vkd.cmdBlitImage(commandBuffer, context.getImage(), m_imageLayout, *m_dstImage, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion, vk::VK_FILTER_NEAREST);
}
void ImageBlitToImage::verify (VerifyContext& context, size_t commandIndex)
{
public:
SubmitRenderPass (const vector<RenderPassCommand*>& commands);
- ~SubmitRenderPass (void) {}
+ ~SubmitRenderPass (void);
const char* getName (void) const { return "SubmitRenderPass"; }
void logPrepare (TestLog&, size_t) const;
{
}
+SubmitRenderPass::~SubmitRenderPass()
+{
+ for (size_t cmdNdx = 0; cmdNdx < m_commands.size(); cmdNdx++)
+ delete m_commands[cmdNdx];
+}
+
void SubmitRenderPass::logPrepare (TestLog& log, size_t commandIndex) const
{
const string sectionName (de::toString(commandIndex) + ":" + getName());
vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
vk::VK_ACCESS_TRANSFER_READ_BIT,
- vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
vk::VK_QUEUE_FAMILY_IGNORED,
OP_IMAGE_DESTROY,
OP_IMAGE_BINDMEMORY,
- OP_IMAGE_TRANSITION_TO_GENERAL,
+ OP_IMAGE_TRANSITION_LAYOUT,
OP_IMAGE_COPY_TO_BUFFER,
OP_IMAGE_COPY_FROM_BUFFER,
STAGE_RENDER_PASS
};
-bool isWriteAccess (vk::VkAccessFlagBits access)
+vk::VkAccessFlags getWriteAccessFlags (void)
{
- switch (access)
- {
-
- case vk::VK_ACCESS_INDIRECT_COMMAND_READ_BIT: return false;
- case vk::VK_ACCESS_INDEX_READ_BIT: return false;
- case vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT: return false;
- case vk::VK_ACCESS_UNIFORM_READ_BIT: return false;
- case vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT: return false;
- case vk::VK_ACCESS_SHADER_READ_BIT: return false;
- case vk::VK_ACCESS_SHADER_WRITE_BIT: return true;
- case vk::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT: return false;
- case vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT: return true;
- case vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT: return false;
- case vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT: return true;
- case vk::VK_ACCESS_TRANSFER_READ_BIT: return false;
- case vk::VK_ACCESS_TRANSFER_WRITE_BIT: return true;
- case vk::VK_ACCESS_HOST_READ_BIT: return false;
- case vk::VK_ACCESS_HOST_WRITE_BIT: return true;
- case vk::VK_ACCESS_MEMORY_READ_BIT: return false;
- case vk::VK_ACCESS_MEMORY_WRITE_BIT: return true;
+ return vk::VK_ACCESS_SHADER_WRITE_BIT
+ | vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
+ | vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT
+ | vk::VK_ACCESS_TRANSFER_WRITE_BIT
+ | vk::VK_ACCESS_HOST_WRITE_BIT
+ | vk::VK_ACCESS_MEMORY_WRITE_BIT;
+}
- default:
- DE_FATAL("Unknown access");
- return true;
- }
+bool isWriteAccess (vk::VkAccessFlagBits access)
+{
+ return (getWriteAccessFlags() & access) != 0;
}
class CacheState
{
public:
- CacheState (vk::VkPipelineStageFlags allowedStages, vk::VkAccessFlags allowedAccesses);
+ CacheState (vk::VkPipelineStageFlags allowedStages, vk::VkAccessFlags allowedAccesses);
- bool isValid (vk::VkPipelineStageFlagBits stage,
- vk::VkAccessFlagBits access) const;
+ bool isValid (vk::VkPipelineStageFlagBits stage,
+ vk::VkAccessFlagBits access) const;
- void perform (vk::VkPipelineStageFlagBits stage,
- vk::VkAccessFlagBits access);
+ void perform (vk::VkPipelineStageFlagBits stage,
+ vk::VkAccessFlagBits access);
- void submitCommandBuffer (void);
+ void submitCommandBuffer (void);
+ void waitForIdle (void);
- void getFullBarrier (vk::VkPipelineStageFlags& srcStages,
- vk::VkAccessFlags& srcAccesses,
- vk::VkPipelineStageFlags& dstStages,
- vk::VkAccessFlags& dstAccesses) const;
+ void getFullBarrier (vk::VkPipelineStageFlags& srcStages,
+ vk::VkAccessFlags& srcAccesses,
+ vk::VkPipelineStageFlags& dstStages,
+ vk::VkAccessFlags& dstAccesses) const;
+
+ void barrier (vk::VkPipelineStageFlags srcStages,
+ vk::VkAccessFlags srcAccesses,
+ vk::VkPipelineStageFlags dstStages,
+ vk::VkAccessFlags dstAccesses);
- void barrier (vk::VkPipelineStageFlags srcStages,
- vk::VkAccessFlags srcAccesses,
- vk::VkPipelineStageFlags dstStages,
- vk::VkAccessFlags dstAccesses);
+ void imageLayoutBarrier (vk::VkPipelineStageFlags srcStages,
+ vk::VkAccessFlags srcAccesses,
+ vk::VkPipelineStageFlags dstStages,
+ vk::VkAccessFlags dstAccesses);
- void fullBarrier (void);
+ void checkImageLayoutBarrier (vk::VkPipelineStageFlags srcStages,
+ vk::VkAccessFlags srcAccesses,
+ vk::VkPipelineStageFlags dstStages,
+ vk::VkAccessFlags dstAccesses);
// Everything is clean and there is no need for barriers
- bool isClean (void) const;
+ bool isClean (void) const;
+ vk::VkPipelineStageFlags getAllowedStages (void) const { return m_allowedStages; }
+ vk::VkAccessFlags getAllowedAcceses (void) const { return m_allowedAccesses; }
private:
// Limit which stages and accesses are used by the CacheState tracker
const vk::VkPipelineStageFlags m_allowedStages;
// [dstStage][srcStage] = srcAccesses
// In stage dstStage write srcAccesses from srcStage are not yet available
vk::VkAccessFlags m_unavailableWriteOperations[PIPELINESTAGE_LAST][PIPELINESTAGE_LAST];
+ // Latest pipeline transition is not available in stage
+ bool m_unavailableLayoutTransition[PIPELINESTAGE_LAST];
// [dstStage] = dstAccesses
// In stage dstStage ops with dstAccesses are not yet visible
vk::VkAccessFlags m_invisibleOperations[PIPELINESTAGE_LAST];
// There are no incomplete read operations initially
m_incompleteOperations[dstStage] = 0;
+ // There are no incomplete layout transitions
+ m_unavailableLayoutTransition[dstStage] = false;
+
for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= m_allowedStages; srcStage_ <<= 1)
{
const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
const PipelineStage dstStage = pipelineStageFlagToPipelineStage(stage);
// Previous operations are not visible to access on stage
- if ((m_invisibleOperations[dstStage] & access) != 0)
+ if (m_unavailableLayoutTransition[dstStage] || (m_invisibleOperations[dstStage] & access) != 0)
return false;
if (isWriteAccess(access))
m_allowedAccesses);
}
+void CacheState::waitForIdle (void)
+{
+ // Make all writes available
+ barrier(m_allowedStages,
+ m_allowedAccesses & getWriteAccessFlags(),
+ m_allowedStages,
+ 0);
+
+ // Make all writes visible on device side
+ barrier(m_allowedStages,
+ 0,
+ m_allowedStages & (~vk::VK_PIPELINE_STAGE_HOST_BIT),
+ m_allowedAccesses);
+}
+
void CacheState::getFullBarrier (vk::VkPipelineStageFlags& srcStages,
vk::VkAccessFlags& srcAccesses,
vk::VkPipelineStageFlags& dstStages,
srcStages |= dstStage_;
srcAccesses |= m_unavailableWriteOperations[dstStage][srcStage];
}
+
+ if (m_unavailableLayoutTransition[dstStage] && !m_unavailableLayoutTransition[srcStage])
+ {
+ // Add dependency between srcStage and dstStage if layout transition has not completed in dstStage,
+ // but has completed in srcStage.
+ dstStages |= dstStage_;
+ srcStages |= dstStage_;
+ }
}
}
DE_ASSERT((dstAccesses & (~m_allowedAccesses)) == 0);
}
+void CacheState::checkImageLayoutBarrier (vk::VkPipelineStageFlags srcStages,
+ vk::VkAccessFlags srcAccesses,
+ vk::VkPipelineStageFlags dstStages,
+ vk::VkAccessFlags dstAccesses)
+{
+ DE_ASSERT((srcStages & (~m_allowedStages)) == 0);
+ DE_ASSERT((srcAccesses & (~m_allowedAccesses)) == 0);
+ DE_ASSERT((dstStages & (~m_allowedStages)) == 0);
+ DE_ASSERT((dstAccesses & (~m_allowedAccesses)) == 0);
+
+ DE_UNREF(srcStages);
+ DE_UNREF(srcAccesses);
+
+ DE_UNREF(dstStages);
+ DE_UNREF(dstAccesses);
+
+#if defined(DE_DEBUG)
+ // Check that all stages have completed before srcStages or are in srcStages.
+ {
+ vk::VkPipelineStageFlags completedStages = srcStages;
+
+ for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= srcStages; srcStage_ <<= 1)
+ {
+ const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
+
+ if ((srcStage_ & srcStages) == 0)
+ continue;
+
+ completedStages |= (~m_incompleteOperations[srcStage]);
+ }
+
+ DE_ASSERT((completedStages & m_allowedStages) == m_allowedStages);
+ }
+
+ // Check that any write is available at least in one stage. Since all stages are complete even single flush is enough.
+ if ((getWriteAccessFlags() & m_allowedAccesses) != 0 && (srcAccesses & getWriteAccessFlags()) == 0)
+ {
+ bool anyWriteAvailable = false;
+
+ for (vk::VkPipelineStageFlags dstStage_ = 1; dstStage_ <= m_allowedStages; dstStage_ <<= 1)
+ {
+ const PipelineStage dstStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)dstStage_);
+
+ if ((dstStage_ & m_allowedStages) == 0)
+ continue;
+
+ for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= m_allowedStages; srcStage_ <<= 1)
+ {
+ const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
+
+ if ((srcStage_ & m_allowedStages) == 0)
+ continue;
+
+ if (m_unavailableWriteOperations[dstStage][srcStage] != (getWriteAccessFlags() & m_allowedAccesses))
+ {
+ anyWriteAvailable = true;
+ break;
+ }
+ }
+ }
+
+ DE_ASSERT(anyWriteAvailable);
+ }
+#endif
+}
+
+void CacheState::imageLayoutBarrier (vk::VkPipelineStageFlags srcStages,
+ vk::VkAccessFlags srcAccesses,
+ vk::VkPipelineStageFlags dstStages,
+ vk::VkAccessFlags dstAccesses)
+{
+ checkImageLayoutBarrier(srcStages, srcAccesses, dstStages, dstAccesses);
+
+ for (vk::VkPipelineStageFlags dstStage_ = 1; dstStage_ <= m_allowedStages; dstStage_ <<= 1)
+ {
+ const PipelineStage dstStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)dstStage_);
+
+ if ((dstStage_ & m_allowedStages) == 0)
+ continue;
+
+ // All stages are incomplete after the barrier except each dstStage in it self.
+ m_incompleteOperations[dstStage] = m_allowedStages & (~dstStage_);
+
+ // All memory operations are invisible unless they are listed in dstAccess
+ m_invisibleOperations[dstStage] = m_allowedAccesses & (~dstAccesses);
+
+ // Layout transition is unavailable in stage unless it was listed in dstStages
+ m_unavailableLayoutTransition[dstStage]= (dstStage_ & dstStages) == 0;
+
+ for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= m_allowedStages; srcStage_ <<= 1)
+ {
+ const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
+
+ if ((srcStage_ & m_allowedStages) == 0)
+ continue;
+
+ // All write operations are available after layout transition
+ m_unavailableWriteOperations[dstStage][srcStage] = 0;
+ }
+ }
+}
+
void CacheState::barrier (vk::VkPipelineStageFlags srcStages,
vk::VkAccessFlags srcAccesses,
vk::VkPipelineStageFlags dstStages,
{
vk::VkPipelineStageFlags oldIncompleteOperations[PIPELINESTAGE_LAST];
vk::VkAccessFlags oldUnavailableWriteOperations[PIPELINESTAGE_LAST][PIPELINESTAGE_LAST];
+ bool oldUnavailableLayoutTransition[PIPELINESTAGE_LAST];
deMemcpy(oldIncompleteOperations, m_incompleteOperations, sizeof(oldIncompleteOperations));
deMemcpy(oldUnavailableWriteOperations, m_unavailableWriteOperations, sizeof(oldUnavailableWriteOperations));
+ deMemcpy(oldUnavailableLayoutTransition, m_unavailableLayoutTransition, sizeof(oldUnavailableLayoutTransition));
for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= srcStages; srcStage_ <<= 1)
{
// Stages that have completed before srcStage have also completed before dstStage
m_incompleteOperations[dstStage] &= oldIncompleteOperations[srcStage];
+ // Image layout transition in srcStage are now available in dstStage
+ m_unavailableLayoutTransition[dstStage] &= oldUnavailableLayoutTransition[srcStage];
+
for (vk::VkPipelineStageFlags sharedStage_ = 1; sharedStage_ <= m_allowedStages; sharedStage_ <<= 1)
{
const PipelineStage sharedStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)sharedStage_);
if (m_incompleteOperations[dstStage] != 0)
return false;
+ // Layout transition has not completed yet
+ if (m_unavailableLayoutTransition[dstStage])
+ return false;
+
for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= m_allowedStages; srcStage_ <<= 1)
{
const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
return true;
}
-void CacheState::fullBarrier (void)
-{
- for (vk::VkPipelineStageFlags dstStage_ = 1; dstStage_ <= m_allowedStages; dstStage_ <<= 1)
- {
- const PipelineStage dstStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)dstStage_);
-
- if ((dstStage_ & m_allowedStages) == 0)
- continue;
-
- // All stages have completed
- m_incompleteOperations[dstStage] = 0;
-
- // All operations are visible
- m_invisibleOperations[dstStage] = 0;
-
- for (vk::VkPipelineStageFlags srcStage_ = 1; srcStage_ <= m_allowedStages; srcStage_ <<= 1)
- {
- const PipelineStage srcStage = pipelineStageFlagToPipelineStage((vk::VkPipelineStageFlagBits)srcStage_);
-
- if ((srcStage_ & m_allowedStages) == 0)
- continue;
-
- // All writes are available
- m_unavailableWriteOperations[dstStage][srcStage] = 0;
- }
- }
-}
-
struct State
{
State (Usage usage, deUint32 seed)
, hasBoundBufferMemory (false)
, hasImage (false)
, hasBoundImageMemory (false)
- , imageHasGeneralLayout (false)
+ , imageLayout (vk::VK_IMAGE_LAYOUT_UNDEFINED)
, imageDefined (false)
, queueIdle (true)
, deviceIdle (true)
{
}
- Stage stage;
- CacheState cache;
- de::Random rng;
+ Stage stage;
+ CacheState cache;
+ de::Random rng;
- bool mapped;
- bool hostInvalidated;
- bool hostFlushed;
- bool memoryDefined;
+ bool mapped;
+ bool hostInvalidated;
+ bool hostFlushed;
+ bool memoryDefined;
- bool hasBuffer;
- bool hasBoundBufferMemory;
+ bool hasBuffer;
+ bool hasBoundBufferMemory;
- bool hasImage;
- bool hasBoundImageMemory;
- bool imageHasGeneralLayout;
- bool imageDefined;
+ bool hasImage;
+ bool hasBoundImageMemory;
+ vk::VkImageLayout imageLayout;
+ bool imageDefined;
- bool queueIdle;
- bool deviceIdle;
+ bool queueIdle;
+ bool deviceIdle;
- bool commandBufferIsEmpty;
+ bool commandBufferIsEmpty;
};
void getAvailableOps (const State& state, bool supportsBuffers, bool supportsImages, Usage usage, vector<Op>& ops)
if (state.hasBoundImageMemory)
{
- if (!state.imageHasGeneralLayout)
- {
- ops.push_back(OP_IMAGE_TRANSITION_TO_GENERAL);
- }
- else
+ ops.push_back(OP_IMAGE_TRANSITION_LAYOUT);
+
{
if (usage & USAGE_TRANSFER_DST
- && state.imageHasGeneralLayout
+ && (state.imageLayout == vk::VK_IMAGE_LAYOUT_GENERAL
+ || state.imageLayout == vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
&& state.cache.isValid(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_WRITE_BIT))
{
ops.push_back(OP_IMAGE_COPY_FROM_BUFFER);
}
if (usage & USAGE_TRANSFER_SRC
- && state.imageHasGeneralLayout
+ && (state.imageLayout == vk::VK_IMAGE_LAYOUT_GENERAL
+ || state.imageLayout == vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
&& state.imageDefined
&& state.cache.isValid(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT))
{
}
}
- // \todo Add other usages?
+ // \todo [2016-03-09 mika] Add other usages?
if (((usage & USAGE_VERTEX_BUFFER) && state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT))
|| ((usage & USAGE_INDEX_BUFFER) && state.cache.isValid(vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, vk::VK_ACCESS_INDEX_READ_BIT)))
ops.push_back(OP_RENDERPASS_BEGIN);
DE_FATAL("Unknown stage");
}
-void applyOp (State& state, const Memory& memory, Op op)
+bool layoutSupportedByUsage (Usage usage, vk::VkImageLayout layout)
+{
+ switch (layout)
+ {
+ case vk::VK_IMAGE_LAYOUT_GENERAL:
+ return true;
+
+ case vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
+ return (usage & USAGE_COLOR_ATTACHMENT) != 0;
+
+ case vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
+ return (usage & USAGE_DEPTH_STENCIL_ATTACHMENT) != 0;
+
+ case vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
+ return (usage & USAGE_DEPTH_STENCIL_ATTACHMENT) != 0;
+
+ case vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
+ // \todo [2016-03-09 mika] Should include input attachment
+ return (usage & USAGE_TEXTURE_SAMPLED) != 0;
+
+ case vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
+ return (usage & USAGE_TRANSFER_SRC) != 0;
+
+ case vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
+ return (usage & USAGE_TRANSFER_DST) != 0;
+
+ case vk::VK_IMAGE_LAYOUT_PREINITIALIZED:
+ return true;
+
+ default:
+ DE_FATAL("Unknown layout");
+ return false;
+ }
+}
+
+vk::VkImageLayout getRandomNextLayout (de::Random& rng,
+ Usage usage,
+ vk::VkImageLayout previousLayout)
+{
+ const vk::VkImageLayout layouts[] =
+ {
+ vk::VK_IMAGE_LAYOUT_GENERAL,
+ vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
+ vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL,
+ vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
+ vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ };
+ size_t possibleLayoutCount = 0;
+
+ for (size_t layoutNdx = 0; layoutNdx < DE_LENGTH_OF_ARRAY(layouts); layoutNdx++)
+ {
+ const vk::VkImageLayout layout = layouts[layoutNdx];
+
+ if (layoutSupportedByUsage(usage, layout) && layout != previousLayout)
+ possibleLayoutCount++;
+ }
+
+ size_t nextLayoutNdx = ((size_t)rng.getUint64()) % possibleLayoutCount;
+
+ for (size_t layoutNdx = 0; layoutNdx < DE_LENGTH_OF_ARRAY(layouts); layoutNdx++)
+ {
+ const vk::VkImageLayout layout = layouts[layoutNdx];
+
+ if (layoutSupportedByUsage(usage, layout) && layout != previousLayout)
+ {
+ if (nextLayoutNdx == 0)
+ return layout;
+ else
+ nextLayoutNdx--;
+ }
+ }
+
+ DE_FATAL("Unreachable");
+ return vk::VK_IMAGE_LAYOUT_UNDEFINED;
+}
+
+void applyOp (State& state, const Memory& memory, Op op, Usage usage)
{
switch (op)
{
state.memoryDefined = true;
state.imageDefined = false;
- state.imageHasGeneralLayout = false;
+ state.imageLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
state.rng.getUint32();
break;
state.hasImage = false;
state.hasBoundImageMemory = false;
- state.imageHasGeneralLayout = false;
+ state.imageLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
state.imageDefined = false;
break;
state.hasBoundImageMemory = true;
break;
- case OP_IMAGE_TRANSITION_TO_GENERAL:
+ case OP_IMAGE_TRANSITION_LAYOUT:
+ {
DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER);
DE_ASSERT(state.hasImage);
DE_ASSERT(state.hasBoundImageMemory);
- state.imageHasGeneralLayout = true;
+ // \todo [2016-03-09 mika] Support linear tiling and predefined data
+ const vk::VkImageLayout srcLayout = state.rng.getFloat() < 0.9f ? state.imageLayout : vk::VK_IMAGE_LAYOUT_UNDEFINED;
+ const vk::VkImageLayout dstLayout = getRandomNextLayout(state.rng, usage, srcLayout);
+
+ vk::VkPipelineStageFlags dirtySrcStages;
+ vk::VkAccessFlags dirtySrcAccesses;
+ vk::VkPipelineStageFlags dirtyDstStages;
+ vk::VkAccessFlags dirtyDstAccesses;
+
+ vk::VkPipelineStageFlags srcStages;
+ vk::VkAccessFlags srcAccesses;
+ vk::VkPipelineStageFlags dstStages;
+ vk::VkAccessFlags dstAccesses;
+
+ state.cache.getFullBarrier(dirtySrcStages, dirtySrcAccesses, dirtyDstStages, dirtyDstAccesses);
+
+ // Try masking some random bits
+ srcStages = dirtySrcStages;
+ srcAccesses = dirtySrcAccesses;
+
+ dstStages = state.cache.getAllowedStages() & state.rng.getUint32();
+ dstAccesses = state.cache.getAllowedAcceses() & state.rng.getUint32();
+
+ // If there are no bits in dst stage mask use all stages
+ dstStages = dstStages ? dstStages : state.cache.getAllowedStages();
+
+ if (!srcStages)
+ srcStages = dstStages;
+
+ if (srcLayout == vk::VK_IMAGE_LAYOUT_UNDEFINED)
+ state.imageDefined = false;
+
+ state.commandBufferIsEmpty = false;
+ state.imageLayout = dstLayout;
state.memoryDefined = false;
+ state.cache.imageLayoutBarrier(srcStages, srcAccesses, dstStages, dstAccesses);
break;
+ }
case OP_QUEUE_WAIT_FOR_IDLE:
DE_ASSERT(state.stage == STAGE_HOST);
DE_ASSERT(!state.queueIdle);
state.queueIdle = true;
+
+ state.cache.waitForIdle();
break;
case OP_DEVICE_WAIT_FOR_IDLE:
state.queueIdle = true;
state.deviceIdle = true;
+
+ state.cache.waitForIdle();
break;
case OP_COMMAND_BUFFER_BEGIN:
state.stage = STAGE_HOST;
state.queueIdle = false;
state.deviceIdle = false;
- // \todo Should this set all device reads ready?
break;
case OP_BUFFER_COPY_FROM_BUFFER:
state.commandBufferIsEmpty = false;
state.memoryDefined = true;
state.imageDefined = false;
- state.imageHasGeneralLayout = false;
+ state.imageLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;
state.cache.perform(vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_ACCESS_TRANSFER_WRITE_BIT);
break;
de::MovePtr<CmdCommand> createCmdCommand (de::Random& rng,
const State& state,
- Op op)
+ Op op,
+ Usage usage)
{
switch (op)
{
case OP_BUFFER_COPY_TO_IMAGE: return de::MovePtr<CmdCommand>(new BufferCopyToImage());
case OP_BUFFER_COPY_FROM_IMAGE: return de::MovePtr<CmdCommand>(new BufferCopyFromImage(rng.getUint32()));
- case OP_IMAGE_TRANSITION_TO_GENERAL: return de::MovePtr<CmdCommand>(new ImageTransition());
+ case OP_IMAGE_TRANSITION_LAYOUT:
+ {
+ DE_ASSERT(state.stage == STAGE_COMMAND_BUFFER);
+ DE_ASSERT(state.hasImage);
+ DE_ASSERT(state.hasBoundImageMemory);
+
+ const vk::VkImageLayout srcLayout = rng.getFloat() < 0.9f ? state.imageLayout : vk::VK_IMAGE_LAYOUT_UNDEFINED;
+ const vk::VkImageLayout dstLayout = getRandomNextLayout(rng, usage, srcLayout);
+
+ vk::VkPipelineStageFlags dirtySrcStages;
+ vk::VkAccessFlags dirtySrcAccesses;
+ vk::VkPipelineStageFlags dirtyDstStages;
+ vk::VkAccessFlags dirtyDstAccesses;
- case OP_IMAGE_COPY_TO_BUFFER: return de::MovePtr<CmdCommand>(new ImageCopyToBuffer());
- case OP_IMAGE_COPY_FROM_BUFFER: return de::MovePtr<CmdCommand>(new ImageCopyFromBuffer(rng.getUint32()));
- case OP_IMAGE_COPY_TO_IMAGE: return de::MovePtr<CmdCommand>(new ImageCopyToImage());
- case OP_IMAGE_COPY_FROM_IMAGE: return de::MovePtr<CmdCommand>(new ImageCopyFromImage(rng.getUint32()));
+ vk::VkPipelineStageFlags srcStages;
+ vk::VkAccessFlags srcAccesses;
+ vk::VkPipelineStageFlags dstStages;
+ vk::VkAccessFlags dstAccesses;
+
+ state.cache.getFullBarrier(dirtySrcStages, dirtySrcAccesses, dirtyDstStages, dirtyDstAccesses);
+
+ // Try masking some random bits
+ srcStages = dirtySrcStages;
+ srcAccesses = dirtySrcAccesses;
+
+ dstStages = state.cache.getAllowedStages() & rng.getUint32();
+ dstAccesses = state.cache.getAllowedAcceses() & rng.getUint32();
+
+ // If there are no bits in dst stage mask use all stages
+ dstStages = dstStages ? dstStages : state.cache.getAllowedStages();
+
+ if (!srcStages)
+ srcStages = dstStages;
+
+ return de::MovePtr<CmdCommand>(new ImageTransition(srcStages, srcAccesses, dstStages, dstAccesses, srcLayout, dstLayout));
+ }
+
+ case OP_IMAGE_COPY_TO_BUFFER: return de::MovePtr<CmdCommand>(new ImageCopyToBuffer(state.imageLayout));
+ case OP_IMAGE_COPY_FROM_BUFFER: return de::MovePtr<CmdCommand>(new ImageCopyFromBuffer(rng.getUint32(), state.imageLayout));
+ case OP_IMAGE_COPY_TO_IMAGE: return de::MovePtr<CmdCommand>(new ImageCopyToImage(state.imageLayout));
+ case OP_IMAGE_COPY_FROM_IMAGE: return de::MovePtr<CmdCommand>(new ImageCopyFromImage(rng.getUint32(), state.imageLayout));
case OP_IMAGE_BLIT_TO_IMAGE:
{
const BlitScale scale = rng.getBool() ? BLIT_SCALE_20 : BLIT_SCALE_10;
- return de::MovePtr<CmdCommand>(new ImageBlitToImage(scale));
+ return de::MovePtr<CmdCommand>(new ImageBlitToImage(scale, state.imageLayout));
}
case OP_IMAGE_BLIT_FROM_IMAGE:
{
const BlitScale scale = rng.getBool() ? BLIT_SCALE_20 : BLIT_SCALE_10;
- return de::MovePtr<CmdCommand>(new ImageBlitFromImage(rng.getUint32(), scale));
+ return de::MovePtr<CmdCommand>(new ImageBlitFromImage(rng.getUint32(), scale, state.imageLayout));
}
case OP_PIPELINE_BARRIER_GLOBAL:
DE_FATAL("Unknown op");
}
- return de::MovePtr<CmdCommand>(new PipelineBarrier(srcStages, srcAccesses, dstStages, dstAccesses, type));
+ if (type == PipelineBarrier::TYPE_IMAGE)
+ return de::MovePtr<CmdCommand>(new PipelineBarrier(srcStages, srcAccesses, dstStages, dstAccesses, type, tcu::just(state.imageLayout)));
+ else
+ return de::MovePtr<CmdCommand>(new PipelineBarrier(srcStages, srcAccesses, dstStages, dstAccesses, type, tcu::nothing<vk::VkImageLayout>()));
}
default:
size_t& opNdx,
size_t opCount)
{
- // \todo Exception safety
vector<RenderPassCommand*> commands;
- for (; opNdx < opCount; opNdx++)
+ try
{
- vector<Op> ops;
+ for (; opNdx < opCount; opNdx++)
+ {
+ vector<Op> ops;
- getAvailableOps(state, memory.getSupportBuffers(), memory.getSupportImages(), usage, ops);
+ getAvailableOps(state, memory.getSupportBuffers(), memory.getSupportImages(), usage, ops);
- DE_ASSERT(!ops.empty());
+ DE_ASSERT(!ops.empty());
- {
- const Op op = nextOpRng.choose<Op>(ops.begin(), ops.end());
-
- if (op == OP_RENDERPASS_END)
- {
- break;
- }
- else
{
- de::Random rng (state.rng);
+ const Op op = nextOpRng.choose<Op>(ops.begin(), ops.end());
- commands.push_back(createRenderPassCommand(rng, state, op).release());
- applyOp(state, memory, op);
+ if (op == OP_RENDERPASS_END)
+ {
+ break;
+ }
+ else
+ {
+ de::Random rng (state.rng);
- DE_ASSERT(state.rng == rng);
+ commands.push_back(createRenderPassCommand(rng, state, op).release());
+ applyOp(state, memory, op, usage);
+
+ DE_ASSERT(state.rng == rng);
+ }
}
}
+
+ applyOp(state, memory, OP_RENDERPASS_END, usage);
+ return de::MovePtr<CmdCommand>(new SubmitRenderPass(commands));
}
+ catch (...)
+ {
+ for (size_t commandNdx = 0; commandNdx < commands.size(); commandNdx++)
+ delete commands[commandNdx];
- applyOp(state, memory, OP_RENDERPASS_END);
- return de::MovePtr<CmdCommand>(new SubmitRenderPass(commands));
+ throw;
+ }
}
de::MovePtr<Command> createCmdCommands (const Memory& memory,
size_t& opNdx,
size_t opCount)
{
- // \todo Exception safety
vector<CmdCommand*> commands;
- for (; opNdx < opCount; opNdx++)
+ try
{
- vector<Op> ops;
+ for (; opNdx < opCount; opNdx++)
+ {
+ vector<Op> ops;
- getAvailableOps(state, memory.getSupportBuffers(), memory.getSupportImages(), usage, ops);
+ getAvailableOps(state, memory.getSupportBuffers(), memory.getSupportImages(), usage, ops);
- DE_ASSERT(!ops.empty());
+ DE_ASSERT(!ops.empty());
- {
- const Op op = nextOpRng.choose<Op>(ops.begin(), ops.end());
-
- if (op == OP_COMMAND_BUFFER_END)
- {
- break;
- }
- else
{
- // \note Command needs to known the state before the operation
- if (op == OP_RENDERPASS_BEGIN)
+ const Op op = nextOpRng.choose<Op>(ops.begin(), ops.end());
+
+ if (op == OP_COMMAND_BUFFER_END)
{
- applyOp(state, memory, op);
- commands.push_back(createRenderPassCommands(memory, nextOpRng, state, usage, opNdx, opCount).release());
+ break;
}
else
{
- de::Random rng (state.rng);
+ // \note Command needs to known the state before the operation
+ if (op == OP_RENDERPASS_BEGIN)
+ {
+ applyOp(state, memory, op, usage);
+ commands.push_back(createRenderPassCommands(memory, nextOpRng, state, usage, opNdx, opCount).release());
+ }
+ else
+ {
+ de::Random rng (state.rng);
- commands.push_back(createCmdCommand(rng, state, op).release());
- applyOp(state, memory, op);
+ commands.push_back(createCmdCommand(rng, state, op, usage).release());
+ applyOp(state, memory, op, usage);
- DE_ASSERT(state.rng == rng);
- }
+ DE_ASSERT(state.rng == rng);
+ }
+ }
}
}
+
+ applyOp(state, memory, OP_COMMAND_BUFFER_END, usage);
+ return de::MovePtr<Command>(new SubmitCommandBuffer(commands));
}
+ catch (...)
+ {
+ for (size_t commandNdx = 0; commandNdx < commands.size(); commandNdx++)
+ delete commands[commandNdx];
- applyOp(state, memory, OP_COMMAND_BUFFER_END);
- return de::MovePtr<Command>(new SubmitCommandBuffer(commands));
+ throw;
+ }
}
void createCommands (vector<Command*>& commands,
if (op == OP_COMMAND_BUFFER_BEGIN)
{
- applyOp(state, memory, op);
+ applyOp(state, memory, op, usage);
commands.push_back(createCmdCommands(memory, nextOpRng, state, usage, opNdx, opCount).release());
}
else
de::Random rng (state.rng);
commands.push_back(createHostCommand(op, rng, usage, sharingMode).release());
- applyOp(state, memory, op);
+ applyOp(state, memory, op, usage);
// Make sure that random generator is in sync
DE_ASSERT(state.rng == rng);
tcu::TestStatus MemoryTestInstance::iterate (void)
{
- // \todo Split different stages over multiple iterations
+ // \todo [2016-03-09 mika] Split different stages over multiple iterations
if (m_memoryTypeNdx < m_memoryProperties.memoryTypeCount)
{
TestLog& log = m_context.getTestContext().getLog();