#include "vkDeviceUtil.hpp"
#include "vkPrograms.hpp"
#include "vkTypeUtil.hpp"
+#include "vkImageUtil.hpp"
#include "tcuTestLog.hpp"
#include "tcuFormatUtil.hpp"
+#include "tcuTextureUtil.hpp"
+#include "tcuImageCompare.hpp"
+
+#include "rrRenderer.hpp"
#include "deUniquePtr.hpp"
"void main (void) { o_color = vec4(1.0, 0.0, 1.0, 1.0); }\n");
}
+class RefVertexShader : public rr::VertexShader
+{
+public:
+ RefVertexShader (void)
+ : rr::VertexShader(1, 0)
+ {
+ m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
+ }
+
+ void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
+ {
+ for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
+ {
+ packets[packetNdx]->position = rr::readVertexAttribFloat(inputs[0],
+ packets[packetNdx]->instanceNdx,
+ packets[packetNdx]->vertexNdx);
+ }
+ }
+};
+
+class RefFragmentShader : public rr::FragmentShader
+{
+public:
+ RefFragmentShader (void)
+ : rr::FragmentShader(0, 1)
+ {
+ m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
+ }
+
+ void shadeFragments (rr::FragmentPacket*, const int numPackets, const rr::FragmentShadingContext& context) const
+ {
+ for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
+ {
+ for (int fragNdx = 0; fragNdx < rr::NUM_FRAGMENTS_PER_PACKET; ++fragNdx)
+ {
+ rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f));
+ }
+ }
+ }
+};
+
+void renderReferenceTriangle (const tcu::PixelBufferAccess& dst, const tcu::Vec4 (&vertices)[3])
+{
+ const RefVertexShader vertShader;
+ const RefFragmentShader fragShader;
+ const rr::Program program (&vertShader, &fragShader);
+ const rr::MultisamplePixelBufferAccess colorBuffer = rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(dst);
+ const rr::RenderTarget renderTarget (colorBuffer);
+ const rr::RenderState renderState ((rr::ViewportState(colorBuffer)));
+ const rr::Renderer renderer;
+ const rr::VertexAttrib vertexAttribs[] =
+ {
+ rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 0, vertices[0].getPtr())
+ };
+
+ renderer.draw(rr::DrawCommand(renderState,
+ renderTarget,
+ program,
+ DE_LENGTH_OF_ARRAY(vertexAttribs),
+ &vertexAttribs[0],
+ rr::PrimitiveList(rr::PRIMITIVETYPE_TRIANGLES, DE_LENGTH_OF_ARRAY(vertices), 0)));
+}
+
tcu::TestStatus renderTriangleTest (Context& context)
{
const VkDevice vkDevice = context.getDevice();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
SimpleAllocator memAlloc (vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
const tcu::IVec2 renderSize (256, 256);
+ const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
+ const tcu::Vec4 clearColor (0.125f, 0.25f, 0.75f, 1.0f);
const tcu::Vec4 vertices[] =
{
}
{
- const VkClearValue clearValue = makeClearValueColorF32(0.125f, 0.25f, 0.75f, 1.0f);
+ const VkClearValue clearValue = makeClearValueColorF32(clearColor[0],
+ clearColor[1],
+ clearColor[2],
+ clearColor[3]);
const VkRenderPassBeginInfo passBeginParams =
{
VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // sType
VK_CHECK(vk.waitForFences(vkDevice, 1u, &fence.get(), DE_TRUE, ~0ull));
}
- // Log image
+ // Read results, render reference, compare
{
- const VkMappedMemoryRange range =
+ const tcu::TextureFormat tcuFormat = vk::mapVkFormat(colorFormat);
+ const VkMappedMemoryRange range =
{
VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, // sType
DE_NULL, // pNext
0, // offset
imageSizeBytes, // size
};
- void* imagePtr = readImageBufferMemory->getHostPtr();
+ const tcu::ConstPixelBufferAccess resultAccess (tcuFormat, renderSize.x(), renderSize.y(), 1, readImageBufferMemory->getHostPtr());
VK_CHECK(vk.invalidateMappedMemoryRanges(vkDevice, 1u, &range));
- context.getTestContext().getLog() << TestLog::Image("Result", "Result", tcu::ConstPixelBufferAccess(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), renderSize.x(), renderSize.y(), 1, imagePtr));
+
+ {
+ tcu::TextureLevel refImage (tcuFormat, renderSize.x(), renderSize.y());
+ const tcu::UVec4 threshold (0u);
+ const tcu::IVec3 posDeviation (1,1,0);
+
+ tcu::clear(refImage.getAccess(), clearColor);
+ renderReferenceTriangle(refImage.getAccess(), vertices);
+
+ if (tcu::intThresholdPositionDeviationCompare(context.getTestContext().getLog(),
+ "ComparisonResult",
+ "Image comparison result",
+ refImage.getAccess(),
+ resultAccess,
+ threshold,
+ posDeviation,
+ false,
+ tcu::COMPARE_LOG_RESULT))
+ return tcu::TestStatus::pass("Rendering succeeded");
+ else
+ return tcu::TestStatus::fail("Image comparison failed");
+ }
}
return tcu::TestStatus::pass("Rendering succeeded");
"}\n");
}
-Move<VkDevice> createTestDevice (const InstanceInterface& vki, VkPhysicalDevice physicalDevice)
+Move<VkDevice> createTestDevice (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, deUint32 *outQueueFamilyIndex)
{
VkDeviceQueueCreateInfo queueInfo;
VkDeviceCreateInfo deviceInfo;
size_t queueNdx;
const float queuePriority = 1.0f;
+ const deUint32 queueCount = 2u;
const vector<VkQueueFamilyProperties> queueProps = getPhysicalDeviceQueueFamilyProperties(vki, physicalDevice);
const VkPhysicalDeviceFeatures physicalDeviceFeatures = getPhysicalDeviceFeatures(vki, physicalDevice);
for (queueNdx = 0; queueNdx < queueProps.size(); queueNdx++)
{
- if ((queueProps[queueNdx].queueFlags & VK_QUEUE_GRAPHICS_BIT) == VK_QUEUE_GRAPHICS_BIT)
+ if ((queueProps[queueNdx].queueFlags & VK_QUEUE_GRAPHICS_BIT) == VK_QUEUE_GRAPHICS_BIT && (queueProps[queueNdx].queueCount >= queueCount))
break;
}
+ if (queueNdx >= queueProps.size())
+ {
+ // No queue family index found
+ std::ostringstream msg;
+ msg << "Cannot create device with " << queueCount << " graphics queues";
+
+ throw tcu::NotSupportedError(msg.str());
+ }
+
deMemset(&queueInfo, 0, sizeof(queueInfo));
deMemset(&deviceInfo, 0, sizeof(deviceInfo));
queueInfo.pNext = DE_NULL;
queueInfo.flags = (VkDeviceQueueCreateFlags)0u;
queueInfo.queueFamilyIndex = (deUint32)queueNdx;
- queueInfo.queueCount = 2u;
+ queueInfo.queueCount = queueCount;
queueInfo.pQueuePriorities = &queuePriority;
deviceInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
deviceInfo.ppEnabledLayerNames = DE_NULL;
deviceInfo.pEnabledFeatures = &physicalDeviceFeatures;
+ *outQueueFamilyIndex = queueInfo.queueFamilyIndex;
+
return createDevice(vki, physicalDevice, &deviceInfo);
};
imageViewCreateInfo.pNext = DE_NULL;
imageViewCreateInfo.flags = 0;
imageViewCreateInfo.image = image.image.get();
- imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_3D;
+ imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
imageViewCreateInfo.format = imageParameters.format;
imageViewCreateInfo.components = componentMap;
imageViewCreateInfo.subresourceRange = subresourceRange;
commandBufferInfo.commandBufferCount = 1;
VK_CHECK(deviceInterface.allocateCommandBuffers(device, &commandBufferInfo, &commandBuffer));
- *commandBufferRef = vk::Move<VkCommandBuffer>(vk::check<VkCommandBuffer>(commandBuffer), Deleter<VkCommandBuffer>(deviceInterface, device, DE_NULL));
+ *commandBufferRef = vk::Move<VkCommandBuffer>(vk::check<VkCommandBuffer>(commandBuffer), Deleter<VkCommandBuffer>(deviceInterface, device, commandPool));
}
void createFences (const DeviceInterface& deviceInterface, VkDevice device, bool signaled, deUint32 numFences, VkFence* fence)
, setEvent (DE_FALSE)
, waitEvent (DE_FALSE)
{
- createFences(context.getDeviceInterface(), device, DE_NULL, DE_LENGTH_OF_ARRAY(fences), fences);
+ createFences(context.getDeviceInterface(), device, false, DE_LENGTH_OF_ARRAY(fences), fences);
}
~TestContext()
bufferBarriers.resize(0);
imageBarriers.resize(0);
- transferInfo.context = &testContext.context;
+ transferInfo.context = &testContext.context;
transferInfo.commandBuffer = renderInfo.commandBuffer;
transferInfo.width = testContext.renderDimension.x();
transferInfo.height = testContext.renderDimension.y();
{
TestLog& log = context.getTestContext().getLog();
const DeviceInterface& deviceInterface = context.getDeviceInterface();
- const InstanceInterface& instanceInterface = context.getInstanceInterface();
- const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
const VkQueue queue = context.getUniversalQueue();
const deUint32 queueFamilyIdx = context.getUniversalQueueFamilyIndex();
- vk::Move<VkDevice> device = createTestDevice(instanceInterface, physicalDevice);
+ VkDevice device = context.getDevice();
VkResult testStatus;
VkResult fenceStatus;
- TestContext testContext(context, device.get());
+ TestContext testContext(context, device);
VkSubmitInfo submitInfo;
VkMappedMemoryRange range;
void* resultImage;
testContext.renderDimension = tcu::IVec2(256, 256);
testContext.renderSize = sizeof(deUint32) * testContext.renderDimension.x() * testContext.renderDimension.y();
- createCommandBuffer(testContext.context, device.get(), queueFamilyIdx, &testContext.cmdBuffer);
+ createCommandBuffer(testContext.context, device, queueFamilyIdx, &testContext.cmdBuffer);
generateWork(testContext);
initSubmitInfo(&submitInfo, 1);
submitInfo.pCommandBuffers = &testContext.cmdBuffer.get();
- VK_CHECK(deviceInterface.queueSubmit(queue, 1, &submitInfo, testContext.fences[0]));
-
- fenceStatus = deviceInterface.getFenceStatus(device.get(), testContext.fences[0]);
+ // Default status is unsignaled
+ fenceStatus = deviceInterface.getFenceStatus(device, testContext.fences[0]);
if (fenceStatus != VK_NOT_READY)
{
- log << TestLog::Message << "testSynchronizationPrimitives fence should be reset but status is " << fenceStatus << TestLog::EndMessage;
+ log << TestLog::Message << "testSynchronizationPrimitives fence 0 should be reset but status is " << getResultName(fenceStatus) << TestLog::EndMessage;
return tcu::TestStatus::fail("Fence in incorrect state");
}
+ fenceStatus = deviceInterface.getFenceStatus(device, testContext.fences[1]);
+ if (fenceStatus != VK_NOT_READY)
+ {
+ log << TestLog::Message << "testSynchronizationPrimitives fence 1 should be reset but status is " << getResultName(fenceStatus) << TestLog::EndMessage;
+ return tcu::TestStatus::fail("Fence in incorrect state");
+ }
+
+ VK_CHECK(deviceInterface.queueSubmit(queue, 1, &submitInfo, testContext.fences[0]));
- testStatus = deviceInterface.waitForFences(device.get(), 1, &testContext.fences[0], DE_TRUE, DEFAULT_TIMEOUT);
+ // Wait for both fences
+ testStatus = deviceInterface.waitForFences(device, 2, &testContext.fences[0], DE_TRUE, DEFAULT_TIMEOUT);
if (testStatus != VK_TIMEOUT)
{
log << TestLog::Message << "testSynchPrimitives failed to wait for all fences" << TestLog::EndMessage;
return tcu::TestStatus::fail("Failed to wait for mulitple fences");
}
- testStatus = deviceInterface.waitForFences(device.get(),
+ // Wait until timeout (no work has been submited to testContext.fences[1])
+ testStatus = deviceInterface.waitForFences(device,
1,
&testContext.fences[1],
DE_TRUE,
return tcu::TestStatus::fail("failed to wait for single fence");
}
- testStatus = deviceInterface.waitForFences(device.get(), 1, &testContext.fences[0], DE_TRUE, DEFAULT_TIMEOUT);
+ // Wait for testContext.fences[0], assuming that the work can be completed
+ // in the default time + the time given so far since the queueSubmit
+ testStatus = deviceInterface.waitForFences(device, 1, &testContext.fences[0], DE_TRUE, DEFAULT_TIMEOUT);
if (testStatus != VK_SUCCESS)
{
log << TestLog::Message << "testSynchPrimitives failed to wait for a set fence" << TestLog::EndMessage;
return tcu::TestStatus::fail("failed to wait for a set fence");
}
- fenceStatus = deviceInterface.getFenceStatus(device.get(), testContext.fences[0]);
+ // Check that the fence is signaled after the wait
+ fenceStatus = deviceInterface.getFenceStatus(device, testContext.fences[0]);
if (fenceStatus != VK_SUCCESS)
{
- log << TestLog::Message << "testSynchronizationPrimitives fence should be signaled but status is " << fenceStatus << TestLog::EndMessage;
+ log << TestLog::Message << "testSynchronizationPrimitives fence should be signaled but status is " << getResultName(fenceStatus) << TestLog::EndMessage;
return tcu::TestStatus::fail("Fence in incorrect state");
}
range.memory = testContext.renderReadBuffer->getMemory();
range.offset = 0;
range.size = testContext.renderSize;
- VK_CHECK(deviceInterface.invalidateMappedMemoryRanges(device.get(), 1, &range));
+ VK_CHECK(deviceInterface.invalidateMappedMemoryRanges(device, 1, &range));
resultImage = testContext.renderReadBuffer->getHostPtr();
log << TestLog::Image( "result",
1,
resultImage));
- return TestStatus::pass("synchornization-fences passed");
+ return TestStatus::pass("synchronization-fences passed");
}
vk::refdetails::Checked<VkSemaphore> createSemaphore (const DeviceInterface& deviceInterface, const VkDevice& device, const VkAllocationCallbacks* allocationCallbacks)
const DeviceInterface& deviceInterface = context.getDeviceInterface();
const InstanceInterface& instanceInterface = context.getInstanceInterface();
const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
- vk::Move<VkDevice> device = createTestDevice(instanceInterface, physicalDevice);
+ deUint32 queueFamilyIdx;
+ vk::Move<VkDevice> device = createTestDevice(instanceInterface, physicalDevice, &queueFamilyIdx);
VkQueue queue[2];
- const deUint32 queueFamilyIdx = context.getUniversalQueueFamilyIndex();
VkResult testStatus;
TestContext testContext1(context, device.get());
TestContext testContext2(context, device.get());
tcu::Vec4( 0.0f, +0.5f, 0.0f, 1.0f)
};
- testContext1.vertices = vertices1;
- testContext1.numVertices = DE_LENGTH_OF_ARRAY(vertices1);
- testContext1.renderDimension = tcu::IVec2(256, 256);
- testContext1.renderSize = sizeof(deUint32) * testContext1.renderDimension.x() * testContext1.renderDimension.y();
+ testContext1.vertices = vertices1;
+ testContext1.numVertices = DE_LENGTH_OF_ARRAY(vertices1);
+ testContext1.renderDimension = tcu::IVec2(256, 256);
+ testContext1.renderSize = sizeof(deUint32) * testContext1.renderDimension.x() * testContext1.renderDimension.y();
- testContext2.vertices = vertices2;
- testContext2.numVertices = DE_LENGTH_OF_ARRAY(vertices2);
- testContext2.renderDimension = tcu::IVec2(256, 256);
- testContext2.renderSize = sizeof(deUint32) * testContext2.renderDimension.x() * testContext2.renderDimension.y();
+ testContext2.vertices = vertices2;
+ testContext2.numVertices = DE_LENGTH_OF_ARRAY(vertices2);
+ testContext2.renderDimension = tcu::IVec2(256, 256);
+ testContext2.renderSize = sizeof(deUint32) * testContext2.renderDimension.x() * testContext2.renderDimension.y();
createCommandBuffer(testContext1.context, device.get(), queueFamilyIdx, &testContext1.cmdBuffer);
generateWork(testContext1);
// The difference between the two submit infos is that each will use a unique cmd buffer,
// and one will signal a semaphore but not wait on a semaphore, the other will wait on the
// semaphore but not signal a semaphore
- submitInfo[0].pCommandBuffers = &testContext1.cmdBuffer.get();
- submitInfo[1].pCommandBuffers = &testContext2.cmdBuffer.get();
+ submitInfo[0].pCommandBuffers = &testContext1.cmdBuffer.get();
+ submitInfo[1].pCommandBuffers = &testContext2.cmdBuffer.get();
- submitInfo[0].signalSemaphoreCount = 1;
- submitInfo[0].pSignalSemaphores = &semaphore.get();
- submitInfo[1].waitSemaphoreCount = 1;
- submitInfo[1].pWaitSemaphores = &semaphore.get();
+ submitInfo[0].signalSemaphoreCount = 1;
+ submitInfo[0].pSignalSemaphores = &semaphore.get();
+ submitInfo[1].waitSemaphoreCount = 1;
+ submitInfo[1].pWaitSemaphores = &semaphore.get();
VK_CHECK(deviceInterface.queueSubmit(queue[0], 1, &submitInfo[0], testContext1.fences[0]));
const DeviceInterface& deviceInterface = context.getDeviceInterface();
const InstanceInterface& instanceInterface = context.getInstanceInterface();
const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
- vk::Move<VkDevice> device = createTestDevice(instanceInterface, physicalDevice);
+ deUint32 queueFamilyIdx;
+ vk::Move<VkDevice> device = createTestDevice(instanceInterface, physicalDevice, &queueFamilyIdx);
VkQueue queue[2];
- const deUint32 queueFamilyIdx = context.getUniversalQueueFamilyIndex();
VkResult testStatus;
VkResult eventStatus;
TestContext testContext1(context, device.get());
eventStatus = deviceInterface.getEventStatus(device.get(), event.get());
if (eventStatus != VK_EVENT_RESET)
{
- log << TestLog::Message << "testSynchronizationPrimitives event should be reset but status is " << eventStatus << TestLog::EndMessage;
+ log << TestLog::Message << "testSynchronizationPrimitives event should be reset but status is " << getResultName(eventStatus) << TestLog::EndMessage;
return tcu::TestStatus::fail("Event in incorrect status");
}