blob: a6e7c8e8fcfd05fa656e13b4de905200bb4c4ba0 [file] [log] [blame]
/*------------------------------------------------------------------------
* Vulkan Conformance Tests
* ------------------------
*
* Copyright (c) 2020 The Khronos Group Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*//*!
* \file
* \brief Testing acceleration structures in ray query extension
*//*--------------------------------------------------------------------*/
#include "vktRayQueryAccelerationStructuresTests.hpp"
#include <array>
#include <set>
#include <limits>
#include "vkDefs.hpp"
#include "deClock.h"
#include "vktTestCase.hpp"
#include "vktTestGroupUtil.hpp"
#include "vkCmdUtil.hpp"
#include "vkObjUtil.hpp"
#include "vkBuilderUtil.hpp"
#include "vkBarrierUtil.hpp"
#include "vkBufferWithMemory.hpp"
#include "vkImageWithMemory.hpp"
#include "vkTypeUtil.hpp"
#include "vkImageUtil.hpp"
#include "vkRayTracingUtil.hpp"
#include "deRandom.hpp"
#include "tcuTexture.hpp"
#include "tcuTextureUtil.hpp"
#include "tcuTestLog.hpp"
#include "tcuImageCompare.hpp"
#include "tcuFloat.hpp"
namespace vkt
{
namespace RayQuery
{
namespace
{
using namespace vk;
using namespace vkt;
static const VkFlags ALL_RAY_TRACING_STAGES = VK_SHADER_STAGE_RAYGEN_BIT_KHR
| VK_SHADER_STAGE_ANY_HIT_BIT_KHR
| VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR
| VK_SHADER_STAGE_MISS_BIT_KHR
| VK_SHADER_STAGE_INTERSECTION_BIT_KHR
| VK_SHADER_STAGE_CALLABLE_BIT_KHR;
enum ShaderSourcePipeline
{
SSP_GRAPHICS_PIPELINE,
SSP_COMPUTE_PIPELINE,
SSP_RAY_TRACING_PIPELINE
};
enum ShaderSourceType
{
SST_VERTEX_SHADER,
SST_TESSELATION_CONTROL_SHADER,
SST_TESSELATION_EVALUATION_SHADER,
SST_GEOMETRY_SHADER,
SST_FRAGMENT_SHADER,
SST_COMPUTE_SHADER,
SST_RAY_GENERATION_SHADER,
SST_INTERSECTION_SHADER,
SST_ANY_HIT_SHADER,
SST_CLOSEST_HIT_SHADER,
SST_MISS_SHADER,
SST_CALLABLE_SHADER,
};
enum ShaderTestType
{
STT_GENERATE_INTERSECTION = 0,
STT_SKIP_INTERSECTION = 1,
};
enum BottomTestType
{
BTT_TRIANGLES,
BTT_AABBS
};
enum TopTestType
{
TTT_IDENTICAL_INSTANCES,
TTT_DIFFERENT_INSTANCES
};
enum OperationTarget
{
OT_NONE,
OT_TOP_ACCELERATION,
OT_BOTTOM_ACCELERATION
};
enum OperationType
{
OP_NONE,
OP_COPY,
OP_COMPACT,
OP_SERIALIZE
};
enum class InstanceCullFlags
{
NONE,
CULL_DISABLE,
COUNTERCLOCKWISE,
ALL,
};
enum class EmptyAccelerationStructureCase
{
NOT_EMPTY = 0,
INACTIVE_TRIANGLES = 1,
INACTIVE_INSTANCES = 2,
NO_GEOMETRIES_BOTTOM = 3, // geometryCount zero when building.
NO_PRIMITIVES_BOTTOM = 4, // primitiveCount zero when building.
NO_PRIMITIVES_TOP = 5, // primitiveCount zero when building.
};
const deUint32 TEST_WIDTH = 8;
const deUint32 TEST_HEIGHT = 8;
struct TestParams;
class TestConfiguration
{
public:
virtual ~TestConfiguration ();
virtual void initConfiguration (Context& context,
TestParams& testParams) = 0;
virtual void fillCommandBuffer (Context& context,
TestParams& testParams,
VkCommandBuffer commandBuffer,
const VkWriteDescriptorSetAccelerationStructureKHR& rayQueryAccelerationStructureWriteDescriptorSet,
const VkDescriptorImageInfo& resultImageInfo) = 0;
virtual bool verifyImage (BufferWithMemory* resultBuffer,
Context& context,
TestParams& testParams) = 0;
virtual VkFormat getResultImageFormat () = 0;
virtual size_t getResultImageFormatSize () = 0;
virtual VkClearValue getClearValue () = 0;
};
TestConfiguration::~TestConfiguration()
{
}
class SceneBuilder
{
public:
virtual std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> initBottomAccelerationStructures (Context& context,
TestParams& testParams) = 0;
virtual de::MovePtr<TopLevelAccelerationStructure> initTopAccelerationStructure (Context& context,
TestParams& testParams,
std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >& bottomLevelAccelerationStructures) = 0;
};
struct TestParams
{
ShaderSourceType shaderSourceType;
ShaderSourcePipeline shaderSourcePipeline;
vk::VkAccelerationStructureBuildTypeKHR buildType; // are we making AS on CPU or GPU
VkFormat vertexFormat;
bool padVertices;
VkIndexType indexType;
BottomTestType bottomTestType; // what kind of geometry is stored in bottom AS
InstanceCullFlags cullFlags; // Flags for instances, if needed.
bool bottomUsesAOP; // does bottom AS use arrays, or arrays of pointers
bool bottomGeneric; // Bottom created as generic AS type.
TopTestType topTestType; // If instances are identical then bottom geometries must have different vertices/aabbs
bool topUsesAOP; // does top AS use arrays, or arrays of pointers
bool topGeneric; // Top created as generic AS type.
VkBuildAccelerationStructureFlagsKHR buildFlags;
OperationTarget operationTarget;
OperationType operationType;
deUint32 width;
deUint32 height;
deUint32 workerThreadsCount;
EmptyAccelerationStructureCase emptyASCase;
};
deUint32 getShaderGroupHandleSize (const InstanceInterface& vki,
const VkPhysicalDevice physicalDevice)
{
de::MovePtr<RayTracingProperties> rayTracingPropertiesKHR;
rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
return rayTracingPropertiesKHR->getShaderGroupHandleSize();
}
deUint32 getShaderGroupBaseAlignment (const InstanceInterface& vki,
const VkPhysicalDevice physicalDevice)
{
de::MovePtr<RayTracingProperties> rayTracingPropertiesKHR;
rayTracingPropertiesKHR = makeRayTracingProperties(vki, physicalDevice);
return rayTracingPropertiesKHR->getShaderGroupBaseAlignment();
}
VkImageCreateInfo makeImageCreateInfo (deUint32 width, deUint32 height, deUint32 depth, VkFormat format)
{
const VkImageCreateInfo imageCreateInfo =
{
VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkImageCreateFlags)0u, // VkImageCreateFlags flags;
VK_IMAGE_TYPE_3D, // VkImageType imageType;
format, // VkFormat format;
makeExtent3D(width, height, depth), // VkExtent3D extent;
1u, // deUint32 mipLevels;
1u, // deUint32 arrayLayers;
VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
0u, // deUint32 queueFamilyIndexCount;
DE_NULL, // const deUint32* pQueueFamilyIndices;
VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
};
return imageCreateInfo;
}
Move<VkQueryPool> makeQueryPool(const DeviceInterface& vk,
const VkDevice device,
const VkQueryType queryType,
deUint32 queryCount)
{
const VkQueryPoolCreateInfo queryPoolCreateInfo =
{
VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // sType
DE_NULL, // pNext
(VkQueryPoolCreateFlags)0, // flags
queryType, // queryType
queryCount, // queryCount
0u, // pipelineStatistics
};
return createQueryPool(vk, device, &queryPoolCreateInfo);
}
bool registerShaderModule (const DeviceInterface& vkd,
const VkDevice device,
Context& context,
std::vector<de::SharedPtr<Move<VkShaderModule>>>& shaderModules,
std::vector<VkPipelineShaderStageCreateInfo>& shaderCreateInfos,
VkShaderStageFlagBits stage,
const std::string& externalNamePart,
const std::string& internalNamePart)
{
char fullShaderName[40];
snprintf(fullShaderName, 40, externalNamePart.c_str(), internalNamePart.c_str());
std::string fsn = fullShaderName;
if (fsn.empty())
return false;
shaderModules.push_back(makeVkSharedPtr(createShaderModule(vkd, device, context.getBinaryCollection().get(fsn), 0)));
shaderCreateInfos.push_back(
{
VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
DE_NULL,
(VkPipelineShaderStageCreateFlags)0,
stage, // stage
shaderModules.back()->get(), // shader
"main",
DE_NULL, // pSpecializationInfo
});
return true;
}
bool registerShaderModule (const DeviceInterface& vkd,
const VkDevice device,
Context& context,
RayTracingPipeline& rayTracingPipeline,
VkShaderStageFlagBits shaderStage,
const std::string& externalNamePart,
const std::string& internalNamePart,
deUint32 groupIndex)
{
char fullShaderName[40];
snprintf(fullShaderName, 40, externalNamePart.c_str(), internalNamePart.c_str());
std::string fsn = fullShaderName;
if (fsn.empty())
return false;
Move<VkShaderModule> shaderModule = createShaderModule(vkd, device, context.getBinaryCollection().get(fsn), 0);
if (*shaderModule == DE_NULL)
return false;
rayTracingPipeline.addShader(shaderStage, shaderModule, groupIndex);
return true;
}
VkGeometryInstanceFlagsKHR getCullFlags (InstanceCullFlags flags)
{
VkGeometryInstanceFlagsKHR cullFlags = 0u;
if (flags == InstanceCullFlags::CULL_DISABLE || flags == InstanceCullFlags::ALL)
cullFlags |= VK_GEOMETRY_INSTANCE_TRIANGLE_FACING_CULL_DISABLE_BIT_KHR;
if (flags == InstanceCullFlags::COUNTERCLOCKWISE || flags == InstanceCullFlags::ALL)
cullFlags |= VK_GEOMETRY_INSTANCE_TRIANGLE_FRONT_COUNTERCLOCKWISE_BIT_KHR;
return cullFlags;
}
class GraphicsConfiguration : public TestConfiguration
{
public:
virtual ~GraphicsConfiguration ();
void initConfiguration (Context& context,
TestParams& testParams) override;
void fillCommandBuffer (Context& context,
TestParams& testParams,
VkCommandBuffer commandBuffer,
const VkWriteDescriptorSetAccelerationStructureKHR& rayQueryAccelerationStructureWriteDescriptorSet,
const VkDescriptorImageInfo& resultImageInfo) override;
bool verifyImage (BufferWithMemory* resultBuffer,
Context& context,
TestParams& testParams) override;
VkFormat getResultImageFormat () override;
size_t getResultImageFormatSize () override;
VkClearValue getClearValue () override;
protected:
Move<VkDescriptorSetLayout> descriptorSetLayout;
Move<VkDescriptorPool> descriptorPool;
Move<VkDescriptorSet> descriptorSet;
Move<VkPipelineLayout> pipelineLayout;
Move<VkRenderPass> renderPass;
Move<VkFramebuffer> framebuffer;
std::vector<de::SharedPtr<Move<VkShaderModule> > > shaderModules;
Move<VkPipeline> pipeline;
std::vector<tcu::Vec3> vertices;
Move<VkBuffer> vertexBuffer;
de::MovePtr<Allocation> vertexAlloc;
};
GraphicsConfiguration::~GraphicsConfiguration()
{
shaderModules.clear();
}
void GraphicsConfiguration::initConfiguration (Context& context,
TestParams& testParams)
{
const DeviceInterface& vkd = context.getDeviceInterface();
const VkDevice device = context.getDevice();
const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
Allocator& allocator = context.getDefaultAllocator();
descriptorSetLayout = DescriptorSetLayoutBuilder()
.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_ALL_GRAPHICS)
.addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, VK_SHADER_STAGE_ALL_GRAPHICS)
.build(vkd, device);
descriptorPool = DescriptorPoolBuilder()
.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
.addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
descriptorSet = makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
pipelineLayout = makePipelineLayout(vkd, device, descriptorSetLayout.get());
std::vector<std::string> rayQueryTestName;
rayQueryTestName.push_back("as_triangle");
rayQueryTestName.push_back("as_aabb");
const std::map<ShaderSourceType,std::vector<std::string>> shaderNames =
{
//idx: 0 1 2 3 4
//shader: vert, tesc, tese, geom, frag,
{ SST_VERTEX_SHADER, { "vert_%s", "", "", "", "", } },
{ SST_TESSELATION_CONTROL_SHADER, { "vert", "tesc_%s", "tese", "", "", } },
{ SST_TESSELATION_EVALUATION_SHADER, { "vert", "tesc", "tese_%s", "", "", } },
{ SST_GEOMETRY_SHADER, { "vert_vid", "", "", "geom_%s", "", } },
{ SST_FRAGMENT_SHADER, { "vert", "", "", "", "frag_%s", } },
};
auto shaderNameIt = shaderNames.find(testParams.shaderSourceType);
if(shaderNameIt == end(shaderNames))
TCU_THROW(InternalError, "Wrong shader source type");
std::vector<VkPipelineShaderStageCreateInfo> shaderCreateInfos;
bool tescX, teseX, fragX;
registerShaderModule(vkd, device, context, shaderModules, shaderCreateInfos, VK_SHADER_STAGE_VERTEX_BIT, shaderNameIt->second[0], rayQueryTestName[testParams.bottomTestType]);
tescX = registerShaderModule(vkd, device, context, shaderModules, shaderCreateInfos, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, shaderNameIt->second[1], rayQueryTestName[testParams.bottomTestType]);
teseX = registerShaderModule(vkd, device, context, shaderModules, shaderCreateInfos, VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, shaderNameIt->second[2], rayQueryTestName[testParams.bottomTestType]);
registerShaderModule(vkd, device, context, shaderModules, shaderCreateInfos, VK_SHADER_STAGE_GEOMETRY_BIT, shaderNameIt->second[3], rayQueryTestName[testParams.bottomTestType]);
fragX = registerShaderModule(vkd, device, context, shaderModules, shaderCreateInfos, VK_SHADER_STAGE_FRAGMENT_BIT, shaderNameIt->second[4], rayQueryTestName[testParams.bottomTestType]);
const vk::VkSubpassDescription subpassDesc =
{
(vk::VkSubpassDescriptionFlags)0,
vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint
0u, // inputCount
DE_NULL, // pInputAttachments
0u, // colorCount
DE_NULL, // pColorAttachments
DE_NULL, // pResolveAttachments
DE_NULL, // depthStencilAttachment
0u, // preserveCount
DE_NULL, // pPreserveAttachments
};
const vk::VkRenderPassCreateInfo renderPassParams =
{
vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // sType
DE_NULL, // pNext
(vk::VkRenderPassCreateFlags)0,
0u, // attachmentCount
DE_NULL, // pAttachments
1u, // subpassCount
&subpassDesc, // pSubpasses
0u, // dependencyCount
DE_NULL, // pDependencies
};
renderPass = createRenderPass(vkd, device, &renderPassParams);
const vk::VkFramebufferCreateInfo framebufferParams =
{
vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // sType
DE_NULL, // pNext
(vk::VkFramebufferCreateFlags)0,
*renderPass, // renderPass
0u, // attachmentCount
DE_NULL, // pAttachments
testParams.width, // width
testParams.height, // height
1u, // layers
};
framebuffer = createFramebuffer(vkd, device, &framebufferParams);
VkPrimitiveTopology testTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
tcu::Vec3 v0(0.0f, 0.0f, 0.0f);
tcu::Vec3 v1(float(testParams.width) - 1.0f, 0.0f, 0.0f);
tcu::Vec3 v2(0.0f, float(testParams.height) - 1.0f, 0.0f);
tcu::Vec3 v3(float(testParams.width) - 1.0f, float(testParams.height) - 1.0f, 0.0f);
switch (testParams.shaderSourceType)
{
case SST_TESSELATION_CONTROL_SHADER:
case SST_TESSELATION_EVALUATION_SHADER:
testTopology = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
vertices.push_back(v0);
vertices.push_back(v1);
vertices.push_back(v2);
vertices.push_back(v1);
vertices.push_back(v3);
vertices.push_back(v2);
break;
case SST_VERTEX_SHADER:
case SST_GEOMETRY_SHADER:
vertices.push_back(v0);
vertices.push_back(v1);
vertices.push_back(v2);
vertices.push_back(v3);
break;
case SST_FRAGMENT_SHADER:
vertices.push_back( tcu::Vec3(-1.0f, 1.0f, 0.0f) );
vertices.push_back( tcu::Vec3(-1.0f, -1.0f, 0.0f) );
vertices.push_back( tcu::Vec3( 1.0f, 1.0f, 0.0f) );
vertices.push_back( tcu::Vec3( 1.0f, -1.0f, 0.0f) );
break;
default:
TCU_THROW(InternalError, "Wrong shader source type");
}
const VkVertexInputBindingDescription vertexInputBindingDescription =
{
0u, // uint32_t binding;
sizeof(tcu::Vec3), // uint32_t stride;
VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
};
const VkVertexInputAttributeDescription vertexInputAttributeDescription =
{
0u, // uint32_t location;
0u, // uint32_t binding;
VK_FORMAT_R32G32B32_SFLOAT, // VkFormat format;
0u, // uint32_t offset;
};
const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo =
{
VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
1u, // deUint32 vertexBindingDescriptionCount;
&vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
1u, // deUint32 vertexAttributeDescriptionCount;
&vertexInputAttributeDescription // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
};
const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCreateInfo =
{
VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkPipelineInputAssemblyStateCreateFlags)0, // VkPipelineInputAssemblyStateCreateFlags flags;
testTopology, // VkPrimitiveTopology topology;
VK_FALSE // VkBool32 primitiveRestartEnable;
};
const VkPipelineTessellationStateCreateInfo tessellationStateCreateInfo =
{
VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
VkPipelineTessellationStateCreateFlags(0u), // VkPipelineTessellationStateCreateFlags flags;
3u // deUint32 patchControlPoints;
};
VkViewport viewport = makeViewport(testParams.width, testParams.height);
VkRect2D scissor = makeRect2D(testParams.width, testParams.height);
const VkPipelineViewportStateCreateInfo viewportStateCreateInfo =
{
VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType
DE_NULL, // const void* pNext
(VkPipelineViewportStateCreateFlags)0, // VkPipelineViewportStateCreateFlags flags
1u, // deUint32 viewportCount
&viewport, // const VkViewport* pViewports
1u, // deUint32 scissorCount
&scissor // const VkRect2D* pScissors
};
const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo =
{
VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkPipelineRasterizationStateCreateFlags)0, // VkPipelineRasterizationStateCreateFlags flags;
VK_FALSE, // VkBool32 depthClampEnable;
fragX ? VK_FALSE : VK_TRUE, // VkBool32 rasterizerDiscardEnable;
VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
VK_FRONT_FACE_CLOCKWISE, // VkFrontFace frontFace;
VK_FALSE, // VkBool32 depthBiasEnable;
0.0f, // float depthBiasConstantFactor;
0.0f, // float depthBiasClamp;
0.0f, // float depthBiasSlopeFactor;
1.0f // float lineWidth;
};
const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo =
{
VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags;
VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples;
VK_FALSE, // VkBool32 sampleShadingEnable;
0.0f, // float minSampleShading;
DE_NULL, // const VkSampleMask* pSampleMask;
VK_FALSE, // VkBool32 alphaToCoverageEnable;
VK_FALSE // VkBool32 alphaToOneEnable;
};
const VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo =
{
VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags;
DE_FALSE, // VkBool32 logicOpEnable;
VK_LOGIC_OP_CLEAR, // VkLogicOp logicOp;
0, // deUint32 attachmentCount;
DE_NULL, // const VkPipelineColorBlendAttachmentState* pAttachments;
{ 1.0f, 1.0f, 1.0f, 1.0f } // float blendConstants[4];
};
const VkGraphicsPipelineCreateInfo graphicsPipelineCreateInfo =
{
VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
(VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags;
static_cast<deUint32>(shaderCreateInfos.size()), // deUint32 stageCount;
shaderCreateInfos.data(), // const VkPipelineShaderStageCreateInfo* pStages;
&vertexInputStateCreateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
&inputAssemblyStateCreateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
(tescX||teseX) ? &tessellationStateCreateInfo : DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
fragX ? &viewportStateCreateInfo : DE_NULL, // const VkPipelineViewportStateCreateInfo* pViewportState;
&rasterizationStateCreateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
fragX ? &multisampleStateCreateInfo : DE_NULL, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
DE_NULL, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
fragX ? &colorBlendStateCreateInfo : DE_NULL, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
pipelineLayout.get(), // VkPipelineLayout layout;
renderPass.get(), // VkRenderPass renderPass;
0u, // deUint32 subpass;
DE_NULL, // VkPipeline basePipelineHandle;
0 // int basePipelineIndex;
};
pipeline = createGraphicsPipeline(vkd, device, DE_NULL, &graphicsPipelineCreateInfo);
const VkBufferCreateInfo vertexBufferParams =
{
VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkBufferCreateFlags flags;
VkDeviceSize(sizeof(tcu::Vec3) * vertices.size()), // VkDeviceSize size;
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
VK_BUFFER_USAGE_TRANSFER_DST_BIT, // VkBufferUsageFlags usage;
VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1u, // deUint32 queueFamilyIndexCount;
&queueFamilyIndex // const deUint32* pQueueFamilyIndices;
};
vertexBuffer = createBuffer(vkd, device, &vertexBufferParams);
vertexAlloc = allocator.allocate(getBufferMemoryRequirements(vkd, device, *vertexBuffer), MemoryRequirement::HostVisible);
VK_CHECK(vkd.bindBufferMemory(device, *vertexBuffer, vertexAlloc->getMemory(), vertexAlloc->getOffset()));
// Upload vertex data
deMemcpy(vertexAlloc->getHostPtr(), vertices.data(), vertices.size() * sizeof(tcu::Vec3));
flushAlloc(vkd, device, *vertexAlloc);
}
void GraphicsConfiguration::fillCommandBuffer (Context& context,
TestParams& testParams,
VkCommandBuffer commandBuffer,
const VkWriteDescriptorSetAccelerationStructureKHR& rayQueryAccelerationStructureWriteDescriptorSet,
const VkDescriptorImageInfo& resultImageInfo)
{
const DeviceInterface& vkd = context.getDeviceInterface();
const VkDevice device = context.getDevice();
DescriptorSetUpdateBuilder()
.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &resultImageInfo)
.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &rayQueryAccelerationStructureWriteDescriptorSet)
.update(vkd, device);
const VkRenderPassBeginInfo renderPassBeginInfo =
{
VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
*renderPass, // VkRenderPass renderPass;
*framebuffer, // VkFramebuffer framebuffer;
makeRect2D(testParams.width, testParams.height), // VkRect2D renderArea;
0u, // uint32_t clearValueCount;
DE_NULL // const VkClearValue* pClearValues;
};
VkDeviceSize vertexBufferOffset = 0u;
vkd.cmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
vkd.cmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
vkd.cmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
vkd.cmdBindVertexBuffers(commandBuffer, 0, 1, &vertexBuffer.get(), &vertexBufferOffset);
vkd.cmdDraw(commandBuffer, deUint32(vertices.size()), 1, 0, 0);
vkd.cmdEndRenderPass(commandBuffer);
}
bool GraphicsConfiguration::verifyImage (BufferWithMemory* resultBuffer,
Context& context,
TestParams& testParams)
{
// create result image
const bool allMiss = (testParams.emptyASCase != EmptyAccelerationStructureCase::NOT_EMPTY);
tcu::TextureFormat imageFormat = vk::mapVkFormat(getResultImageFormat());
tcu::ConstPixelBufferAccess resultAccess(imageFormat, testParams.width, testParams.height, 2, resultBuffer->getAllocation().getHostPtr());
// create reference image
std::vector<deUint32> reference(testParams.width * testParams.height * 2);
tcu::PixelBufferAccess referenceAccess(imageFormat, testParams.width, testParams.height, 2, reference.data());
std::vector<std::vector<deUint32>> primitives =
{
{0, 1, 2},
{1, 3, 2}
};
tcu::UVec4 hitValue0 = tcu::UVec4(1, 0, 0, 0);
tcu::UVec4 hitValue1 = tcu::UVec4(1, 0, 0, 0);
tcu::UVec4 missValue = tcu::UVec4(0, 0, 0, 0);
tcu::UVec4 clearValue = tcu::UVec4(0xFF, 0, 0, 0);
switch (testParams.shaderSourceType)
{
case SST_VERTEX_SHADER:
tcu::clear(referenceAccess, clearValue);
for (deUint32 vertexNdx = 0; vertexNdx < 4; ++vertexNdx)
{
if (!allMiss && (vertexNdx == 1 || vertexNdx == 2))
{
referenceAccess.setPixel(hitValue0, vertexNdx, 0, 0);
referenceAccess.setPixel(hitValue1, vertexNdx, 0, 1);
}
else
{
referenceAccess.setPixel(missValue, vertexNdx, 0, 0);
referenceAccess.setPixel(missValue, vertexNdx, 0, 1);
}
}
break;
case SST_TESSELATION_EVALUATION_SHADER:
case SST_TESSELATION_CONTROL_SHADER:
case SST_GEOMETRY_SHADER:
tcu::clear(referenceAccess, clearValue);
for (deUint32 primitiveNdx = 0; primitiveNdx < primitives.size(); ++primitiveNdx)
for (deUint32 vertexNdx = 0; vertexNdx < 3; ++vertexNdx)
{
deUint32 vNdx = primitives[primitiveNdx][vertexNdx];
if (!allMiss && (vNdx==1 || vNdx==2))
{
referenceAccess.setPixel(hitValue0, primitiveNdx, vertexNdx, 0);
referenceAccess.setPixel(hitValue1, primitiveNdx, vertexNdx, 1);
}
else
{
referenceAccess.setPixel(missValue, primitiveNdx, vertexNdx, 0);
referenceAccess.setPixel(missValue, primitiveNdx, vertexNdx, 1);
}
}
break;
case SST_FRAGMENT_SHADER:
tcu::clear(referenceAccess, missValue);
for (deUint32 y = 0; y < testParams.height; ++y)
for (deUint32 x = 0; x < testParams.width; ++x)
{
if (allMiss || ((x + y) % 2) == 0)
continue;
referenceAccess.setPixel(hitValue0, x, y, 0);
referenceAccess.setPixel(hitValue1, x, y, 1);
}
break;
default:
TCU_THROW(InternalError, "Wrong shader source type");
}
// compare result and reference
return tcu::intThresholdCompare(context.getTestContext().getLog(), "Result comparison", "", referenceAccess, resultAccess, tcu::UVec4(0), tcu::COMPARE_LOG_RESULT);
}
VkFormat GraphicsConfiguration::getResultImageFormat ()
{
return VK_FORMAT_R32_UINT;
}
size_t GraphicsConfiguration::getResultImageFormatSize ()
{
return sizeof(deUint32);
}
VkClearValue GraphicsConfiguration::getClearValue ()
{
return makeClearValueColorU32(0xFF, 0u, 0u, 0u);
}
class ComputeConfiguration : public TestConfiguration
{
public:
virtual ~ComputeConfiguration ();
void initConfiguration (Context& context,
TestParams& testParams) override;
void fillCommandBuffer (Context& context,
TestParams& testParams,
VkCommandBuffer commandBuffer,
const VkWriteDescriptorSetAccelerationStructureKHR& rayQueryAccelerationStructureWriteDescriptorSet,
const VkDescriptorImageInfo& resultImageInfo) override;
bool verifyImage (BufferWithMemory* resultBuffer,
Context& context,
TestParams& testParams) override;
VkFormat getResultImageFormat () override;
size_t getResultImageFormatSize () override;
VkClearValue getClearValue () override;
protected:
Move<VkDescriptorSetLayout> descriptorSetLayout;
Move<VkDescriptorPool> descriptorPool;
Move<VkDescriptorSet> descriptorSet;
Move<VkPipelineLayout> pipelineLayout;
Move<VkShaderModule> shaderModule;
Move<VkPipeline> pipeline;
};
ComputeConfiguration::~ComputeConfiguration()
{
}
void ComputeConfiguration::initConfiguration (Context& context,
TestParams& testParams)
{
const DeviceInterface& vkd = context.getDeviceInterface();
const VkDevice device = context.getDevice();
descriptorSetLayout = DescriptorSetLayoutBuilder()
.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
.addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, VK_SHADER_STAGE_COMPUTE_BIT)
.build(vkd, device);
descriptorPool = DescriptorPoolBuilder()
.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
.addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
descriptorSet = makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
pipelineLayout = makePipelineLayout(vkd, device, descriptorSetLayout.get());
std::vector<std::string> rayQueryTestName;
rayQueryTestName.push_back("comp_as_triangle");
rayQueryTestName.push_back("comp_as_aabb");
shaderModule = createShaderModule(vkd, device, context.getBinaryCollection().get(rayQueryTestName[testParams.bottomTestType]), 0u);
const VkPipelineShaderStageCreateInfo pipelineShaderStageParams =
{
VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkPipelineShaderStageCreateFlags flags;
VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlagBits stage;
*shaderModule, // VkShaderModule module;
"main", // const char* pName;
DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
};
const VkComputePipelineCreateInfo pipelineCreateInfo =
{
VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType sType;
DE_NULL, // const void* pNext;
0u, // VkPipelineCreateFlags flags;
pipelineShaderStageParams, // VkPipelineShaderStageCreateInfo stage;
*pipelineLayout, // VkPipelineLayout layout;
DE_NULL, // VkPipeline basePipelineHandle;
0, // deInt32 basePipelineIndex;
};
pipeline = createComputePipeline(vkd, device, DE_NULL, &pipelineCreateInfo);
}
void ComputeConfiguration::fillCommandBuffer (Context& context,
TestParams& testParams,
VkCommandBuffer commandBuffer,
const VkWriteDescriptorSetAccelerationStructureKHR& rayQueryAccelerationStructureWriteDescriptorSet,
const VkDescriptorImageInfo& resultImageInfo)
{
const DeviceInterface& vkd = context.getDeviceInterface();
const VkDevice device = context.getDevice();
DescriptorSetUpdateBuilder()
.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &resultImageInfo)
.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &rayQueryAccelerationStructureWriteDescriptorSet)
.update(vkd, device);
vkd.cmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
vkd.cmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
vkd.cmdDispatch(commandBuffer, testParams.width, testParams.height, 1);
}
bool ComputeConfiguration::verifyImage (BufferWithMemory* resultBuffer,
Context& context,
TestParams& testParams)
{
// create result image
const bool allMiss = (testParams.emptyASCase != EmptyAccelerationStructureCase::NOT_EMPTY);
tcu::TextureFormat imageFormat = vk::mapVkFormat(getResultImageFormat());
tcu::ConstPixelBufferAccess resultAccess(imageFormat, testParams.width, testParams.height, 2, resultBuffer->getAllocation().getHostPtr());
// create reference image
std::vector<deUint32> reference(testParams.width * testParams.height * 2);
tcu::PixelBufferAccess referenceAccess(imageFormat, testParams.width, testParams.height, 2, reference.data());
tcu::UVec4 hitValue0 = tcu::UVec4(1, 0, 0, 0);
tcu::UVec4 hitValue1 = tcu::UVec4(1, 0, 0, 0);
tcu::UVec4 missValue = tcu::UVec4(0, 0, 0, 0);
tcu::clear(referenceAccess, missValue);
for (deUint32 y = 0; y < testParams.height; ++y)
for (deUint32 x = 0; x < testParams.width; ++x)
{
if (allMiss || ((x + y) % 2) == 0)
continue;
referenceAccess.setPixel(hitValue0, x, y, 0);
referenceAccess.setPixel(hitValue1, x, y, 1);
}
// compare result and reference
return tcu::intThresholdCompare(context.getTestContext().getLog(), "Result comparison", "", referenceAccess, resultAccess, tcu::UVec4(0), tcu::COMPARE_LOG_RESULT);
}
VkFormat ComputeConfiguration::getResultImageFormat ()
{
return VK_FORMAT_R32_UINT;
}
size_t ComputeConfiguration::getResultImageFormatSize ()
{
return sizeof(deUint32);
}
VkClearValue ComputeConfiguration::getClearValue ()
{
return makeClearValueColorU32(0xFF, 0u, 0u, 0u);
}
class RayTracingConfiguration : public TestConfiguration
{
public:
virtual ~RayTracingConfiguration ();
void initConfiguration (Context& context,
TestParams& testParams) override;
void fillCommandBuffer (Context& context,
TestParams& testParams,
VkCommandBuffer commandBuffer,
const VkWriteDescriptorSetAccelerationStructureKHR& rayQueryAccelerationStructureWriteDescriptorSet,
const VkDescriptorImageInfo& resultImageInfo) override;
bool verifyImage (BufferWithMemory* resultBuffer,
Context& context,
TestParams& testParams) override;
VkFormat getResultImageFormat () override;
size_t getResultImageFormatSize () override;
VkClearValue getClearValue () override;
protected:
Move<VkDescriptorSetLayout> descriptorSetLayout;
Move<VkDescriptorPool> descriptorPool;
Move<VkDescriptorSet> descriptorSet;
Move<VkPipelineLayout> pipelineLayout;
de::MovePtr<RayTracingPipeline> rayTracingPipeline;
Move<VkPipeline> rtPipeline;
de::MovePtr<BufferWithMemory> raygenShaderBindingTable;
de::MovePtr<BufferWithMemory> hitShaderBindingTable;
de::MovePtr<BufferWithMemory> missShaderBindingTable;
de::MovePtr<BufferWithMemory> callableShaderBindingTable;
std::vector<de::SharedPtr<BottomLevelAccelerationStructure> > bottomLevelAccelerationStructures;
de::MovePtr<TopLevelAccelerationStructure> topLevelAccelerationStructure;
};
RayTracingConfiguration::~RayTracingConfiguration()
{
}
void RayTracingConfiguration::initConfiguration (Context& context,
TestParams& testParams)
{
const InstanceInterface& vki = context.getInstanceInterface();
const DeviceInterface& vkd = context.getDeviceInterface();
const VkDevice device = context.getDevice();
const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
Allocator& allocator = context.getDefaultAllocator();
descriptorSetLayout = DescriptorSetLayoutBuilder()
.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, ALL_RAY_TRACING_STAGES)
.addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
.addSingleBinding(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, ALL_RAY_TRACING_STAGES)
.build(vkd, device);
descriptorPool = DescriptorPoolBuilder()
.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
.addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
.addType(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR)
.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
descriptorSet = makeDescriptorSet(vkd, device, *descriptorPool, *descriptorSetLayout);
pipelineLayout = makePipelineLayout(vkd, device, descriptorSetLayout.get());
rayTracingPipeline = de::newMovePtr<RayTracingPipeline>();
const std::map<ShaderSourceType,std::vector<std::string>> shaderNames =
{
//idx: 0 1 2 3 4 5
//shader: rgen, isect, ahit, chit, miss, call
//group: 0 1 1 1 2 3
{ SST_RAY_GENERATION_SHADER, { "rgen_%s", "", "", "", "", "" } },
{ SST_INTERSECTION_SHADER, { "rgen", "isect_%s", "", "chit_isect", "miss", "" } },
{ SST_ANY_HIT_SHADER, { "rgen", "isect", "ahit_%s", "", "miss", "" } },
{ SST_CLOSEST_HIT_SHADER, { "rgen", "isect", "", "chit_%s", "miss", "" } },
{ SST_MISS_SHADER, { "rgen", "isect", "", "chit", "miss_%s", "" } },
{ SST_CALLABLE_SHADER, { "rgen_call", "", "", "chit", "miss", "call_%s" } },
};
std::vector<std::string> rayQueryTestName;
rayQueryTestName.push_back("as_triangle");
rayQueryTestName.push_back("as_aabb");
auto shaderNameIt = shaderNames.find(testParams.shaderSourceType);
if(shaderNameIt == end(shaderNames))
TCU_THROW(InternalError, "Wrong shader source type");
bool rgenX, isectX, ahitX, chitX, missX, callX;
rgenX = registerShaderModule(vkd, device, context, *rayTracingPipeline, VK_SHADER_STAGE_RAYGEN_BIT_KHR, shaderNameIt->second[0], rayQueryTestName[testParams.bottomTestType], 0);
if (testParams.shaderSourceType == SST_INTERSECTION_SHADER)
isectX = registerShaderModule(vkd, device, context, *rayTracingPipeline, VK_SHADER_STAGE_INTERSECTION_BIT_KHR, shaderNameIt->second[1], rayQueryTestName[testParams.bottomTestType], 1);
else
isectX = false;
ahitX = registerShaderModule(vkd, device, context, *rayTracingPipeline, VK_SHADER_STAGE_ANY_HIT_BIT_KHR, shaderNameIt->second[2], rayQueryTestName[testParams.bottomTestType], 1);
chitX = registerShaderModule(vkd, device, context, *rayTracingPipeline, VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR, shaderNameIt->second[3], rayQueryTestName[testParams.bottomTestType], 1);
missX = registerShaderModule(vkd, device, context, *rayTracingPipeline, VK_SHADER_STAGE_MISS_BIT_KHR, shaderNameIt->second[4], rayQueryTestName[testParams.bottomTestType], 2);
callX = registerShaderModule(vkd, device, context, *rayTracingPipeline, VK_SHADER_STAGE_CALLABLE_BIT_KHR, shaderNameIt->second[5], rayQueryTestName[testParams.bottomTestType], 3);
bool hitX = isectX || ahitX || chitX;
rtPipeline = rayTracingPipeline->createPipeline(vkd, device, *pipelineLayout);
deUint32 shaderGroupHandleSize = getShaderGroupHandleSize(vki, physicalDevice);
deUint32 shaderGroupBaseAlignment = getShaderGroupBaseAlignment(vki, physicalDevice);
if (rgenX) raygenShaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, *rtPipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 0, 1);
if (hitX) hitShaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, *rtPipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 1, 1);
if (missX) missShaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, *rtPipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 2, 1);
if (callX) callableShaderBindingTable = rayTracingPipeline->createShaderBindingTable(vkd, device, *rtPipeline, allocator, shaderGroupHandleSize, shaderGroupBaseAlignment, 3, 1);
}
void RayTracingConfiguration::fillCommandBuffer (Context& context,
TestParams& testParams,
VkCommandBuffer commandBuffer,
const VkWriteDescriptorSetAccelerationStructureKHR& rayQueryAccelerationStructureWriteDescriptorSet,
const VkDescriptorImageInfo& resultImageInfo)
{
const InstanceInterface& vki = context.getInstanceInterface();
const DeviceInterface& vkd = context.getDeviceInterface();
const VkDevice device = context.getDevice();
const VkPhysicalDevice physicalDevice = context.getPhysicalDevice();
Allocator& allocator = context.getDefaultAllocator();
{
de::MovePtr<BottomLevelAccelerationStructure> bottomLevelAccelerationStructure = makeBottomLevelAccelerationStructure();
bottomLevelAccelerationStructure->setGeometryCount(1);
de::SharedPtr<RaytracedGeometryBase> geometry;
if (testParams.shaderSourceType != SST_INTERSECTION_SHADER)
{
tcu::Vec3 v0(0.0f, float(testParams.height), 0.0f);
tcu::Vec3 v1(0.0f, 0.0f, 0.0f);
tcu::Vec3 v2(float(testParams.width), float(testParams.height), 0.0f);
tcu::Vec3 v3(float(testParams.width), 0.0f, 0.0f);
tcu::Vec3 missOffset(0.0f, 0.0f, 0.0f);
if (testParams.shaderSourceType == SST_MISS_SHADER)
missOffset = tcu::Vec3(1.0f + float(testParams.width), 0.0f, 0.0f);
geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, VK_FORMAT_R32G32B32_SFLOAT, VK_INDEX_TYPE_NONE_KHR);
geometry->addVertex(v0 + missOffset);
geometry->addVertex(v1 + missOffset);
geometry->addVertex(v2 + missOffset);
geometry->addVertex(v2 + missOffset);
geometry->addVertex(v1 + missOffset);
geometry->addVertex(v3 + missOffset);
}
else // testParams.shaderSourceType == SST_INTERSECTION_SHADER
{
tcu::Vec3 v0(0.0f, 0.0f, -0.1f);
tcu::Vec3 v1(float(testParams.width), float(testParams.height), 0.1f);
geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_AABBS_KHR, VK_FORMAT_R32G32B32_SFLOAT, VK_INDEX_TYPE_NONE_KHR);
geometry->addVertex(v0);
geometry->addVertex(v1);
}
bottomLevelAccelerationStructure->addGeometry(geometry);
bottomLevelAccelerationStructures.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
for (auto& blas : bottomLevelAccelerationStructures)
blas->createAndBuild(vkd, device, commandBuffer, allocator);
}
topLevelAccelerationStructure = makeTopLevelAccelerationStructure();
topLevelAccelerationStructure->setInstanceCount(1);
topLevelAccelerationStructure->addInstance(bottomLevelAccelerationStructures[0]);
topLevelAccelerationStructure->createAndBuild(vkd, device, commandBuffer, allocator);
const TopLevelAccelerationStructure* topLevelAccelerationStructurePtr = topLevelAccelerationStructure.get();
VkWriteDescriptorSetAccelerationStructureKHR accelerationStructureWriteDescriptorSet =
{
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, // VkStructureType sType;
DE_NULL, // const void* pNext;
1u, // deUint32 accelerationStructureCount;
topLevelAccelerationStructurePtr->getPtr(), // const VkAccelerationStructureKHR* pAccelerationStructures;
};
DescriptorSetUpdateBuilder()
.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &resultImageInfo)
.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &accelerationStructureWriteDescriptorSet)
.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(2u), VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, &rayQueryAccelerationStructureWriteDescriptorSet)
.update(vkd, device);
vkd.cmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *pipelineLayout, 0, 1, &descriptorSet.get(), 0, DE_NULL);
vkd.cmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, *rtPipeline);
deUint32 shaderGroupHandleSize = getShaderGroupHandleSize(vki, physicalDevice);
VkStridedDeviceAddressRegionKHR raygenShaderBindingTableRegion = raygenShaderBindingTable.get() != DE_NULL ? makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, raygenShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize) : makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
VkStridedDeviceAddressRegionKHR hitShaderBindingTableRegion = hitShaderBindingTable.get() != DE_NULL ? makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, hitShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize) : makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
VkStridedDeviceAddressRegionKHR missShaderBindingTableRegion = missShaderBindingTable.get() != DE_NULL ? makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, missShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize) : makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
VkStridedDeviceAddressRegionKHR callableShaderBindingTableRegion = callableShaderBindingTable.get() != DE_NULL ? makeStridedDeviceAddressRegionKHR(getBufferDeviceAddress(vkd, device, callableShaderBindingTable->get(), 0), shaderGroupHandleSize, shaderGroupHandleSize) : makeStridedDeviceAddressRegionKHR(DE_NULL, 0, 0);
cmdTraceRays(vkd,
commandBuffer,
&raygenShaderBindingTableRegion,
&missShaderBindingTableRegion,
&hitShaderBindingTableRegion,
&callableShaderBindingTableRegion,
testParams.width, testParams.height, 1);
}
bool RayTracingConfiguration::verifyImage (BufferWithMemory* resultBuffer,
Context& context,
TestParams& testParams)
{
// create result image
const bool allMiss = (testParams.emptyASCase != EmptyAccelerationStructureCase::NOT_EMPTY);
tcu::TextureFormat imageFormat = vk::mapVkFormat(getResultImageFormat());
tcu::ConstPixelBufferAccess resultAccess(imageFormat, testParams.width, testParams.height, 2, resultBuffer->getAllocation().getHostPtr());
// create reference image
std::vector<deUint32> reference(testParams.width * testParams.height * 2);
tcu::PixelBufferAccess referenceAccess(imageFormat, testParams.width, testParams.height, 2, reference.data());
tcu::UVec4 missValue (0, 0, 0, 0);
tcu::UVec4 hitValue (1, 0, 0, 0);
for (deUint32 y = 0; y < testParams.height; ++y)
for (deUint32 x = 0; x < testParams.width; ++x)
{
if (allMiss || ((x + y) % 2) == 0)
{
referenceAccess.setPixel(missValue, x, y, 0);
referenceAccess.setPixel(missValue, x, y, 1);
}
else
{
referenceAccess.setPixel(hitValue, x, y, 0);
referenceAccess.setPixel(hitValue, x, y, 1);
}
}
// compare result and reference
return tcu::intThresholdCompare(context.getTestContext().getLog(), "Result comparison", "", referenceAccess, resultAccess, tcu::UVec4(0), tcu::COMPARE_LOG_RESULT);
}
VkFormat RayTracingConfiguration::getResultImageFormat ()
{
return VK_FORMAT_R32_UINT;
}
size_t RayTracingConfiguration::getResultImageFormatSize ()
{
return sizeof(deUint32);
}
VkClearValue RayTracingConfiguration::getClearValue ()
{
return makeClearValueColorU32(0xFF, 0u, 0u, 0u);
}
de::SharedPtr<TestConfiguration> createTestConfiguration(const ShaderSourcePipeline& shaderSourcePipeline)
{
switch (shaderSourcePipeline)
{
case SSP_GRAPHICS_PIPELINE:
return de::SharedPtr<TestConfiguration>(new GraphicsConfiguration());
case SSP_COMPUTE_PIPELINE:
return de::SharedPtr<TestConfiguration>(new ComputeConfiguration());
case SSP_RAY_TRACING_PIPELINE:
return de::SharedPtr<TestConfiguration>(new RayTracingConfiguration());
default:
TCU_THROW(InternalError, "Wrong shader source pipeline");
}
return de::SharedPtr<TestConfiguration>();
}
class CheckerboardSceneBuilder : public SceneBuilder
{
public:
std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> initBottomAccelerationStructures (Context& context,
TestParams& testParams) override;
de::MovePtr<TopLevelAccelerationStructure> initTopAccelerationStructure (Context& context,
TestParams& testParams,
std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >& bottomLevelAccelerationStructures) override;
};
std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> CheckerboardSceneBuilder::initBottomAccelerationStructures (Context& context,
TestParams& testParams)
{
DE_UNREF(context);
// Cull flags can only be used with triangles.
DE_ASSERT(testParams.cullFlags == InstanceCullFlags::NONE || testParams.bottomTestType == BTT_TRIANGLES);
std::vector<de::SharedPtr<BottomLevelAccelerationStructure> > result;
const auto instanceFlags = getCullFlags(testParams.cullFlags);
tcu::Vec3 v0(0.0, 1.0, 0.0);
tcu::Vec3 v1(0.0, 0.0, 0.0);
tcu::Vec3 v2(1.0, 1.0, 0.0);
tcu::Vec3 v3(1.0, 0.0, 0.0);
if (testParams.emptyASCase == EmptyAccelerationStructureCase::INACTIVE_TRIANGLES)
{
const auto nanValue = tcu::Float32::nan().asFloat();
v0.x() = nanValue;
v1.x() = nanValue;
v2.x() = nanValue;
v3.x() = nanValue;
}
if (testParams.topTestType == TTT_DIFFERENT_INSTANCES)
{
de::MovePtr<BottomLevelAccelerationStructure> bottomLevelAccelerationStructure = makeBottomLevelAccelerationStructure();
bottomLevelAccelerationStructure->setGeometryCount(1u);
de::SharedPtr<RaytracedGeometryBase> geometry;
if (testParams.bottomTestType == BTT_TRIANGLES)
{
geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, testParams.vertexFormat, testParams.indexType, testParams.padVertices);
if (testParams.indexType == VK_INDEX_TYPE_NONE_KHR)
{
if (instanceFlags == 0u)
{
geometry->addVertex(v0);
geometry->addVertex(v1);
geometry->addVertex(v2);
geometry->addVertex(v2);
geometry->addVertex(v1);
geometry->addVertex(v3);
}
else // Counterclockwise so the flags will be needed for the geometry to be visible.
{
geometry->addVertex(v2);
geometry->addVertex(v1);
geometry->addVertex(v0);
geometry->addVertex(v3);
geometry->addVertex(v1);
geometry->addVertex(v2);
}
}
else // m_data.indexType != VK_INDEX_TYPE_NONE_KHR
{
geometry->addVertex(v0);
geometry->addVertex(v1);
geometry->addVertex(v2);
geometry->addVertex(v3);
if (instanceFlags == 0u)
{
geometry->addIndex(0);
geometry->addIndex(1);
geometry->addIndex(2);
geometry->addIndex(2);
geometry->addIndex(1);
geometry->addIndex(3);
}
else // Counterclockwise so the flags will be needed for the geometry to be visible.
{
geometry->addIndex(2);
geometry->addIndex(1);
geometry->addIndex(0);
geometry->addIndex(3);
geometry->addIndex(1);
geometry->addIndex(2);
}
}
}
else // m_data.bottomTestType == BTT_AABBS
{
geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_AABBS_KHR, testParams.vertexFormat, testParams.indexType, testParams.padVertices);
if (!testParams.padVertices)
{
// Single AABB.
geometry->addVertex(tcu::Vec3(0.0f, 0.0f, -0.1f));
geometry->addVertex(tcu::Vec3(1.0f, 1.0f, 0.1f));
}
else
{
// Multiple AABBs covering the same space.
geometry->addVertex(tcu::Vec3(0.0f, 0.0f, -0.1f));
geometry->addVertex(tcu::Vec3(0.5f, 0.5f, 0.1f));
geometry->addVertex(tcu::Vec3(0.5f, 0.5f, -0.1f));
geometry->addVertex(tcu::Vec3(1.0f, 1.0f, 0.1f));
geometry->addVertex(tcu::Vec3(0.0f, 0.5f, -0.1f));
geometry->addVertex(tcu::Vec3(0.5f, 1.0f, 0.1f));
geometry->addVertex(tcu::Vec3(0.5f, 0.0f, -0.1f));
geometry->addVertex(tcu::Vec3(1.0f, 0.5f, 0.1f));
}
}
bottomLevelAccelerationStructure->addGeometry(geometry);
result.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
}
else // m_data.topTestType == TTT_IDENTICAL_INSTANCES
{
tcu::TextureFormat texFormat = mapVkFormat(testParams.vertexFormat);
tcu::Vec3 scale ( 1.0f, 1.0f, 1.0f );
if (tcu::getTextureChannelClass(texFormat.type) == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT)
scale = tcu::Vec3(1.0f / float(testParams.width), 1.0f / float(testParams.height), 1.0f);
// triangle and aabb tests use geometries/aabbs with different vertex positions and the same identity matrix in each instance data
for (deUint32 y = 0; y < testParams.height; ++y)
for (deUint32 x = 0; x < testParams.width; ++x)
{
// let's build a chessboard of geometries
if (((x + y) % 2) == 0)
continue;
tcu::Vec3 xyz((float)x, (float)y, 0.0f);
de::MovePtr<BottomLevelAccelerationStructure> bottomLevelAccelerationStructure = makeBottomLevelAccelerationStructure();
bottomLevelAccelerationStructure->setGeometryCount(1u);
de::SharedPtr<RaytracedGeometryBase> geometry;
if (testParams.bottomTestType == BTT_TRIANGLES)
{
geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_TRIANGLES_KHR, testParams.vertexFormat, testParams.indexType, testParams.padVertices);
if (testParams.indexType == VK_INDEX_TYPE_NONE_KHR)
{
if (instanceFlags == 0u)
{
geometry->addVertex(scale * (xyz + v0));
geometry->addVertex(scale * (xyz + v1));
geometry->addVertex(scale * (xyz + v2));
geometry->addVertex(scale * (xyz + v2));
geometry->addVertex(scale * (xyz + v1));
geometry->addVertex(scale * (xyz + v3));
}
else // Counterclockwise so the flags will be needed for the geometry to be visible.
{
geometry->addVertex(scale * (xyz + v2));
geometry->addVertex(scale * (xyz + v1));
geometry->addVertex(scale * (xyz + v0));
geometry->addVertex(scale * (xyz + v3));
geometry->addVertex(scale * (xyz + v1));
geometry->addVertex(scale * (xyz + v2));
}
}
else
{
geometry->addVertex(scale * (xyz + v0));
geometry->addVertex(scale * (xyz + v1));
geometry->addVertex(scale * (xyz + v2));
geometry->addVertex(scale * (xyz + v3));
if (instanceFlags == 0u)
{
geometry->addIndex(0);
geometry->addIndex(1);
geometry->addIndex(2);
geometry->addIndex(2);
geometry->addIndex(1);
geometry->addIndex(3);
}
else // Counterclockwise so the flags will be needed for the geometry to be visible.
{
geometry->addIndex(2);
geometry->addIndex(1);
geometry->addIndex(0);
geometry->addIndex(3);
geometry->addIndex(1);
geometry->addIndex(2);
}
}
}
else // testParams.bottomTestType == BTT_AABBS
{
geometry = makeRaytracedGeometry(VK_GEOMETRY_TYPE_AABBS_KHR, testParams.vertexFormat, testParams.indexType, testParams.padVertices);
if (!testParams.padVertices)
{
// Single AABB.
geometry->addVertex(scale * (xyz + tcu::Vec3(0.0f, 0.0f, -0.1f)));
geometry->addVertex(scale * (xyz + tcu::Vec3(1.0f, 1.0f, 0.1f)));
}
else
{
// Multiple AABBs covering the same space.
geometry->addVertex(scale * (xyz + tcu::Vec3(0.0f, 0.0f, -0.1f)));
geometry->addVertex(scale * (xyz + tcu::Vec3(0.5f, 0.5f, 0.1f)));
geometry->addVertex(scale * (xyz + tcu::Vec3(0.5f, 0.5f, -0.1f)));
geometry->addVertex(scale * (xyz + tcu::Vec3(1.0f, 1.0f, 0.1f)));
geometry->addVertex(scale * (xyz + tcu::Vec3(0.0f, 0.5f, -0.1f)));
geometry->addVertex(scale * (xyz + tcu::Vec3(0.5f, 1.0f, 0.1f)));
geometry->addVertex(scale * (xyz + tcu::Vec3(0.5f, 0.0f, -0.1f)));
geometry->addVertex(scale * (xyz + tcu::Vec3(1.0f, 0.5f, 0.1f)));
}
}
bottomLevelAccelerationStructure->addGeometry(geometry);
result.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(bottomLevelAccelerationStructure.release()));
}
}
return result;
}
de::MovePtr<TopLevelAccelerationStructure> CheckerboardSceneBuilder::initTopAccelerationStructure (Context& context,
TestParams& testParams,
std::vector<de::SharedPtr<BottomLevelAccelerationStructure> >& bottomLevelAccelerationStructures)
{
DE_UNREF(context);
const auto instanceCount = testParams.width * testParams.height / 2u;
const auto instanceFlags = getCullFlags(testParams.cullFlags);
de::MovePtr<TopLevelAccelerationStructure> result = makeTopLevelAccelerationStructure();
result->setInstanceCount(instanceCount);
if (testParams.topTestType == TTT_DIFFERENT_INSTANCES)
{
for (deUint32 y = 0; y < testParams.height; ++y)
for (deUint32 x = 0; x < testParams.width; ++x)
{
if (((x + y) % 2) == 0)
continue;
const VkTransformMatrixKHR transformMatrixKHR =
{
{ // float matrix[3][4];
{ 1.0f, 0.0f, 0.0f, (float)x },
{ 0.0f, 1.0f, 0.0f, (float)y },
{ 0.0f, 0.0f, 1.0f, 0.0f },
}
};
result->addInstance(bottomLevelAccelerationStructures[0], transformMatrixKHR, 0u, 0xFFu, 0u, instanceFlags);
}
}
else // testParams.topTestType == TTT_IDENTICAL_INSTANCES
{
tcu::TextureFormat texFormat = mapVkFormat(testParams.vertexFormat);
tcu::Vec3 scale ( 1.0f, 1.0f, 1.0f );
if (tcu::getTextureChannelClass(texFormat.type) == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT)
scale = tcu::Vec3(float(testParams.width), float(testParams.height), 1.0f);
const VkTransformMatrixKHR transformMatrixKHR =
{
{ // float matrix[3][4];
{ scale.x(), 0.0f, 0.0f, 0.0f },
{ 0.0f, scale.y(), 0.0f, 0.0f },
{ 0.0f, 0.0f, scale.z(), 0.0f },
}
};
deUint32 currentInstanceIndex = 0;
for (deUint32 y = 0; y < testParams.height; ++y)
for (deUint32 x = 0; x < testParams.width; ++x)
{
if (((x + y) % 2) == 0)
continue;
result->addInstance(bottomLevelAccelerationStructures[currentInstanceIndex++], transformMatrixKHR, 0u, 0xFFu, 0u, instanceFlags);
}
}
return result;
}
void commonASTestsCheckSupport(Context& context)
{
context.requireInstanceFunctionality("VK_KHR_get_physical_device_properties2");
context.requireDeviceFunctionality("VK_KHR_acceleration_structure");
context.requireDeviceFunctionality("VK_KHR_ray_query");
const VkPhysicalDeviceRayQueryFeaturesKHR& rayQueryFeaturesKHR = context.getRayQueryFeatures();
if (rayQueryFeaturesKHR.rayQuery == DE_FALSE)
TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayQueryFeaturesKHR.rayQuery");
const VkPhysicalDeviceAccelerationStructureFeaturesKHR& accelerationStructureFeaturesKHR = context.getAccelerationStructureFeatures();
if (accelerationStructureFeaturesKHR.accelerationStructure == DE_FALSE)
TCU_THROW(TestError, "VK_KHR_ray_query requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructure");
}
class RayQueryASBasicTestCase : public TestCase
{
public:
RayQueryASBasicTestCase (tcu::TestContext& context, const char* name, const char* desc, const TestParams& data);
~RayQueryASBasicTestCase (void);
virtual void checkSupport (Context& context) const;
virtual void initPrograms (SourceCollections& programCollection) const;
virtual TestInstance* createInstance (Context& context) const;
protected:
TestParams m_data;
};
class RayQueryASFuncArgTestCase : public RayQueryASBasicTestCase
{
public:
RayQueryASFuncArgTestCase (tcu::TestContext& context, const char* name, const char* desc, const TestParams& data);
~RayQueryASFuncArgTestCase (void) {}
virtual void initPrograms (SourceCollections& programCollection) const;
};
class RayQueryASBasicTestInstance : public TestInstance
{
public:
RayQueryASBasicTestInstance (Context& context,
const TestParams& data);
~RayQueryASBasicTestInstance (void);
tcu::TestStatus iterate (void);
protected:
bool iterateNoWorkers (void);
bool iterateWithWorkers (void);
de::MovePtr<BufferWithMemory> runTest (TestConfiguration* testConfiguration,
SceneBuilder* sceneBuilder,
const deUint32 workerThreadsCount);
private:
TestParams m_data;
};
RayQueryASBasicTestCase::RayQueryASBasicTestCase (tcu::TestContext& context, const char* name, const char* desc, const TestParams& data)
: vkt::TestCase (context, name, desc)
, m_data (data)
{
}
RayQueryASBasicTestCase::~RayQueryASBasicTestCase (void)
{
}
void RayQueryASBasicTestCase::checkSupport (Context& context) const
{
commonASTestsCheckSupport(context);
const VkPhysicalDeviceFeatures2& features2 = context.getDeviceFeatures2();
if ((m_data.shaderSourceType == SST_TESSELATION_CONTROL_SHADER ||
m_data.shaderSourceType == SST_TESSELATION_EVALUATION_SHADER) &&
features2.features.tessellationShader == DE_FALSE )
TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceFeatures2.tessellationShader");
if (m_data.shaderSourceType == SST_GEOMETRY_SHADER &&
features2.features.geometryShader == DE_FALSE )
TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceFeatures2.geometryShader");
if (m_data.shaderSourceType == SST_RAY_GENERATION_SHADER ||
m_data.shaderSourceType == SST_INTERSECTION_SHADER ||
m_data.shaderSourceType == SST_ANY_HIT_SHADER ||
m_data.shaderSourceType == SST_CLOSEST_HIT_SHADER ||
m_data.shaderSourceType == SST_MISS_SHADER ||
m_data.shaderSourceType == SST_CALLABLE_SHADER)
{
context.requireDeviceFunctionality("VK_KHR_ray_tracing_pipeline");
const VkPhysicalDeviceRayTracingPipelineFeaturesKHR& rayTracingPipelineFeaturesKHR = context.getRayTracingPipelineFeatures();
if(rayTracingPipelineFeaturesKHR.rayTracingPipeline == DE_FALSE )
TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceRayTracingPipelineFeaturesKHR.rayTracingPipeline");
}
switch (m_data.shaderSourceType)
{
case SST_VERTEX_SHADER:
case SST_TESSELATION_CONTROL_SHADER:
case SST_TESSELATION_EVALUATION_SHADER:
case SST_GEOMETRY_SHADER:
context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_VERTEX_PIPELINE_STORES_AND_ATOMICS);
break;
default:
break;
}
const VkPhysicalDeviceAccelerationStructureFeaturesKHR& accelerationStructureFeaturesKHR = context.getAccelerationStructureFeatures();
if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_HOST_KHR && accelerationStructureFeaturesKHR.accelerationStructureHostCommands == DE_FALSE)
TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceAccelerationStructureFeaturesKHR.accelerationStructureHostCommands");
// Check supported vertex format.
checkAccelerationStructureVertexBufferFormat(context.getInstanceInterface(), context.getPhysicalDevice(), m_data.vertexFormat);
}
void RayQueryASBasicTestCase::initPrograms (SourceCollections& programCollection) const
{
const vk::ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, 0u, true);
// create parts of programs responsible for test execution
std::vector<std::string> rayQueryTest;
std::vector<std::string> rayQueryTestName;
rayQueryTestName.push_back("as_triangle");
rayQueryTestName.push_back("as_aabb");
{
std::stringstream css;
css <<
" float tmin = 0.0;\n"
" float tmax = 1.0;\n"
" vec3 direct = vec3(0.0, 0.0, -1.0);\n"
" rayQueryEXT rq;\n"
" rayQueryInitializeEXT(rq, rqTopLevelAS, " << ((m_data.cullFlags == InstanceCullFlags::NONE) ? "0" : "gl_RayFlagsCullBackFacingTrianglesEXT") << ", 0xFF, origin, tmin, direct, tmax);\n"
" if(rayQueryProceedEXT(rq))\n"
" {\n"
" if (rayQueryGetIntersectionTypeEXT(rq, false)==gl_RayQueryCandidateIntersectionTriangleEXT)\n"
" {\n"
" hitValue.y = 1;\n"
" hitValue.x = 1;\n"
" }\n"
" }\n";
rayQueryTest.push_back(css.str());
}
{
std::stringstream css;
css <<
" float tmin = 0.0;\n"
" float tmax = 1.0;\n"
" vec3 direct = vec3(0.0, 0.0, -1.0);\n"
" rayQueryEXT rq;\n"
" rayQueryInitializeEXT(rq, rqTopLevelAS, 0, 0xFF, origin, tmin, direct, tmax);\n"
" if(rayQueryProceedEXT(rq))\n"
" {\n"
" if (rayQueryGetIntersectionTypeEXT(rq, false)==gl_RayQueryCandidateIntersectionAABBEXT)\n"
" {\n"
" hitValue.y = 1;\n"
" hitValue.x = 1;\n"
" }\n"
" }\n";
rayQueryTest.push_back(css.str());
}
// create all programs
if (m_data.shaderSourcePipeline == SSP_GRAPHICS_PIPELINE)
{
{
std::stringstream css;
css <<
"#version 460 core\n"
"layout (location = 0) in vec3 position;\n"
"out gl_PerVertex\n"
"{\n"
" vec4 gl_Position;\n"
"};\n"
"void main()\n"
"{\n"
" gl_Position = vec4(position, 1.0);\n"
"}\n";
programCollection.glslSources.add("vert") << glu::VertexSource(css.str()) << buildOptions;
}
{
std::stringstream css;
css <<
"#version 460 core\n"
"layout (location = 0) in vec3 position;\n"
"out gl_PerVertex\n"
"{\n"
" vec4 gl_Position;\n"
"};\n"
"layout(location = 0) out int vertexIndex;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(position, 1.0);\n"
" vertexIndex = gl_VertexIndex;\n"
"}\n";
programCollection.glslSources.add("vert_vid") << glu::VertexSource(css.str()) << buildOptions;
}
{
std::stringstream css;
css <<
"#version 460 core\n"
"#extension GL_EXT_ray_query : require\n"
"layout (location = 0) in vec3 position;\n"
"layout(r32ui, set = 0, binding = 0) uniform uimage3D result;\n"
"layout(set = 0, binding = 1) uniform accelerationStructureEXT rqTopLevelAS;\n"
"void main()\n"
"{\n"
" vec3 origin = vec3(float(position.x) + 0.5, float(position.y) + 0.5, 0.5);\n"
" uvec4 hitValue = uvec4(0,0,0,0);\n" <<
rayQueryTest[m_data.bottomTestType] <<
" imageStore(result, ivec3(gl_VertexIndex, 0, 0), uvec4(hitValue.x, 0, 0, 0));\n"
" imageStore(result, ivec3(gl_VertexIndex, 0, 1), uvec4(hitValue.y, 0, 0, 0));\n"
" gl_Position = vec4(position,1);\n"
"}\n";
std::stringstream cssName;
cssName << "vert_" << rayQueryTestName[m_data.bottomTestType];
programCollection.glslSources.add(cssName.str()) << glu::VertexSource(css.str()) << buildOptions;
}
{
std::stringstream css;
css <<
"#version 460 core\n"
"#extension GL_EXT_tessellation_shader : require\n"
"in gl_PerVertex {\n"
" vec4 gl_Position;\n"
"} gl_in[];\n"
"layout(vertices = 3) out;\n"
"void main (void)\n"
"{\n"
" gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
" gl_TessLevelInner[0] = 1;\n"
" gl_TessLevelOuter[0] = 1;\n"
" gl_TessLevelOuter[1] = 1;\n"
" gl_TessLevelOuter[2] = 1;\n"
"}\n";
programCollection.glslSources.add("tesc") << glu::TessellationControlSource(css.str()) << buildOptions;
}
{
std::stringstream css;
css <<
"#version 460 core\n"
"#extension GL_EXT_tessellation_shader : require\n"
"#extension GL_EXT_ray_query : require\n"
"layout(r32ui, set = 0, binding = 0) uniform uimage3D result;\n"
"layout(set = 0, binding = 1) uniform accelerationStructureEXT rqTopLevelAS;\n"
"in gl_PerVertex {\n"
" vec4 gl_Position;\n"
"} gl_in[];\n"
"layout(vertices = 3) out;\n"
"void main (void)\n"
"{\n"
" vec3 origin = vec3(gl_in[gl_InvocationID].gl_Position.x + 0.5, gl_in[gl_InvocationID].gl_Position.y + 0.5, 0.5);\n"
" uvec4 hitValue = uvec4(0,0,0,0);\n" <<
rayQueryTest[m_data.bottomTestType] <<
" imageStore(result, ivec3(gl_PrimitiveID, gl_InvocationID, 0), uvec4(hitValue.x, 0, 0, 0));\n"
" imageStore(result, ivec3(gl_PrimitiveID, gl_InvocationID, 1), uvec4(hitValue.y, 0, 0, 0));\n"
" gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
" gl_TessLevelInner[0] = 1;\n"
" gl_TessLevelOuter[0] = 1;\n"
" gl_TessLevelOuter[1] = 1;\n"
" gl_TessLevelOuter[2] = 1;\n"
"}\n";
std::stringstream cssName;
cssName << "tesc_" << rayQueryTestName[m_data.bottomTestType];
programCollection.glslSources.add(cssName.str()) << glu::TessellationControlSource(css.str()) << buildOptions;
}
{
std::stringstream css;
css <<
"#version 460 core\n"
"#extension GL_EXT_tessellation_shader : require\n"
"#extension GL_EXT_ray_query : require\n"
"layout(triangles, equal_spacing, ccw) in;\n"
"layout(r32ui, set = 0, binding = 0) uniform uimage3D result;\n"
"layout(set = 0, binding = 1) uniform accelerationStructureEXT rqTopLevelAS;\n"
"void main (void)\n"
"{\n"
" for (int i = 0; i < 3; ++i)\n"
" {\n"
" vec3 origin = vec3(gl_in[i].gl_Position.x + 0.5, gl_in[i].gl_Position.y + 0.5, 0.5);\n"
" uvec4 hitValue = uvec4(0,0,0,0);\n" <<
rayQueryTest[m_data.bottomTestType] <<
" imageStore(result, ivec3(gl_PrimitiveID, i, 0), uvec4(hitValue.x, 0, 0, 0));\n"
" imageStore(result, ivec3(gl_PrimitiveID, i, 1), uvec4(hitValue.y, 0, 0, 0));\n"
" }\n"
" gl_Position = gl_in[0].gl_Position;\n"
"}\n";
std::stringstream cssName;
cssName << "tese_" << rayQueryTestName[m_data.bottomTestType];
programCollection.glslSources.add(cssName.str()) << glu::TessellationEvaluationSource(css.str()) << buildOptions;
}
{
std::stringstream css;
css <<
"#version 460 core\n"
"#extension GL_EXT_tessellation_shader : require\n"
"layout(triangles, equal_spacing, ccw) in;\n"
"void main (void)\n"
"{\n"
" gl_Position = gl_in[0].gl_Position;\n"
"}\n";
programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(css.str()) << buildOptions;
}
{
std::stringstream css;
css <<
"#version 460 core\n"
"#extension GL_EXT_ray_query : require\n"
"layout(triangles) in;\n"
"layout (triangle_strip, max_vertices = 4) out;\n"
"layout(r32ui, set = 0, binding = 0) uniform uimage3D result;\n"
"layout(set = 0, binding = 1) uniform accelerationStructureEXT rqTopLevelAS;\n"
"\n"
"in gl_PerVertex {\n"
" vec4 gl_Position;\n"
"} gl_in[];\n"
"layout(location = 0) in int vertexIndex[];\n"
"out gl_PerVertex {\n"
" vec4 gl_Position;\n"
"};\n"
"void main (void)\n"
"{\n"
" // geometry shader may reorder the vertices, keeping only the winding of the triangles.\n"
" // To iterate from the 'first vertex' of the triangle we need to find it first by looking for\n"
" // smallest vertex index value.\n"
" int minVertexIndex = 10000;"
" int firstVertex;"
" for (int i = 0; i < gl_in.length(); ++i)\n"
" {\n"
" if (minVertexIndex > vertexIndex[i])\n"
" {\n"
" minVertexIndex = vertexIndex[i];\n"
" firstVertex = i;\n"
" }\n"
" }\n"
" for (int j = 0; j < gl_in.length(); ++j)\n"
" {\n"
" // iterate starting at firstVertex, possibly wrapping around, so the triangle is\n"
" // always iterated starting from the smallest vertex index, as found above.\n"
" int i = (firstVertex + j) % gl_in.length();\n"
" vec3 origin = vec3(gl_in[i].gl_Position.x + 0.5, gl_in[i].gl_Position.y + 0.5, 0.5);\n"
" uvec4 hitValue = uvec4(0,0,0,0);\n" <<
rayQueryTest[m_data.bottomTestType] <<
" imageStore(result, ivec3(gl_PrimitiveIDIn, j, 0), uvec4(hitValue.x, 0, 0, 0));\n"
" imageStore(result, ivec3(gl_PrimitiveIDIn, j, 1), uvec4(hitValue.y, 0, 0, 0));\n"
" gl_Position = gl_in[i].gl_Position;\n"
" EmitVertex();\n"
" }\n"
" EndPrimitive();\n"
"}\n";
std::stringstream cssName;
cssName << "geom_" << rayQueryTestName[m_data.bottomTestType];
programCollection.glslSources.add(cssName.str()) << glu::GeometrySource(css.str()) << buildOptions;
}
{
std::stringstream css;
css <<
"#version 460 core\n"
"#extension GL_EXT_ray_query : require\n"
"layout(r32ui, set = 0, binding = 0) uniform uimage3D result;\n"
"layout(set = 0, binding = 1) uniform accelerationStructureEXT rqTopLevelAS;\n"
"void main()\n"
"{\n"
" vec3 origin = vec3(gl_FragCoord.x, gl_FragCoord.y, 0.5);\n"
" uvec4 hitValue = uvec4(0,0,0,0);\n" <<
rayQueryTest[m_data.bottomTestType] <<
" imageStore(result, ivec3(gl_FragCoord.xy-vec2(0.5,0.5), 0), uvec4(hitValue.x, 0, 0, 0));\n"
" imageStore(result, ivec3(gl_FragCoord.xy-vec2(0.5,0.5), 1), uvec4(hitValue.y, 0, 0, 0));\n"
"}\n";
std::stringstream cssName;
cssName << "frag_" << rayQueryTestName[m_data.bottomTestType];
programCollection.glslSources.add(cssName.str()) << glu::FragmentSource(css.str()) << buildOptions;
}
}
else if (m_data.shaderSourcePipeline == SSP_COMPUTE_PIPELINE)
{
{
std::stringstream css;
css <<
"#version 460 core\n"
"#extension GL_EXT_ray_query : require\n"
"layout(r32ui, set = 0, binding = 0) uniform uimage3D result;\n"
"layout(set = 0, binding = 1) uniform accelerationStructureEXT rqTopLevelAS;\n"
"void main()\n"
"{\n"
" vec3 origin = vec3(float(gl_GlobalInvocationID.x) + 0.5, float(gl_GlobalInvocationID.y) + 0.5, 0.5);\n"
" uvec4 hitValue = uvec4(0,0,0,0);\n" <<
rayQueryTest[m_data.bottomTestType] <<
" imageStore(result, ivec3(gl_GlobalInvocationID.xy, 0), uvec4(hitValue.x, 0, 0, 0));\n"
" imageStore(result, ivec3(gl_GlobalInvocationID.xy, 1), uvec4(hitValue.y, 0, 0, 0));\n"
"}\n";
std::stringstream cssName;
cssName << "comp_" << rayQueryTestName[m_data.bottomTestType];
programCollection.glslSources.add(cssName.str()) << glu::ComputeSource(css.str()) << buildOptions;
}
}
else if (m_data.shaderSourcePipeline == SSP_RAY_TRACING_PIPELINE)
{
{
std::stringstream css;
css <<
"#version 460 core\n"
"#extension GL_EXT_ray_tracing : require\n"
"layout(location = 0) rayPayloadEXT uvec4 hitValue;\n"
"layout(r32ui, set = 0, binding = 0) uniform uimage3D result;\n"
"layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
"void main()\n"
"{\n"
" float tmin = 0.0;\n"
" float tmax = 1.0;\n"
" vec3 origin = vec3(float(gl_LaunchIDEXT.x) + 0.5, float(gl_LaunchIDEXT.y) + 0.5, 0.5);\n"
" vec3 direct = vec3(0.0, 0.0, -1.0);\n"
" hitValue = uvec4(0,0,0,0);\n"
" traceRayEXT(topLevelAS, 0, 0xFF, 0, 0, 0, origin, tmin, direct, tmax, 0);\n"
" imageStore(result, ivec3(gl_LaunchIDEXT.xy, 0), uvec4(hitValue.x, 0, 0, 0));\n"
" imageStore(result, ivec3(gl_LaunchIDEXT.xy, 1), uvec4(hitValue.y, 0, 0, 0));\n"
"}\n";
programCollection.glslSources.add("rgen") << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
}
{
std::stringstream css;
css <<
"#version 460 core\n"
"#extension GL_EXT_ray_tracing : require\n"
"#extension GL_EXT_ray_query : require\n"
"layout(r32ui, set = 0, binding = 0) uniform uimage3D result;\n"
"layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
"layout(set = 0, binding = 2) uniform accelerationStructureEXT rqTopLevelAS;\n"
"void main()\n"
"{\n"
" vec3 origin = vec3(float(gl_LaunchIDEXT.x) + 0.5, float(gl_LaunchIDEXT.y) + 0.5, 0.5);\n"
" uvec4 hitValue = uvec4(0,0,0,0);\n" <<
rayQueryTest[m_data.bottomTestType] <<
" imageStore(result, ivec3(gl_LaunchIDEXT.xy, 0), uvec4(hitValue.x, 0, 0, 0));\n"
" imageStore(result, ivec3(gl_LaunchIDEXT.xy, 1), uvec4(hitValue.y, 0, 0, 0));\n"
"}\n";
std::stringstream cssName;
cssName << "rgen_" << rayQueryTestName[m_data.bottomTestType];
programCollection.glslSources.add(cssName.str()) << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
}
{
std::stringstream css;
css <<
"#version 460 core\n"
"#extension GL_EXT_ray_tracing : require\n"
"struct CallValue\n{\n"
" vec3 origin;\n"
" uvec4 hitValue;\n"
"};\n"
"layout(location = 0) callableDataEXT CallValue param;\n"
"layout(r32ui, set = 0, binding = 0) uniform uimage3D result;\n"
"layout(set = 0, binding = 1) uniform accelerationStructureEXT topLevelAS;\n"
"void main()\n"
"{\n"
" param.origin = vec3(float(gl_LaunchIDEXT.x) + 0.5, float(gl_LaunchIDEXT.y) + 0.5, 0.5);\n"
" param.hitValue = uvec4(0, 0, 0, 0);\n"
" executeCallableEXT(0, 0);\n"
" imageStore(result, ivec3(gl_LaunchIDEXT.xy, 0), uvec4(param.hitValue.x, 0, 0, 0));\n"
" imageStore(result, ivec3(gl_LaunchIDEXT.xy, 1), uvec4(param.hitValue.y, 0, 0, 0));\n"
"}\n";
programCollection.glslSources.add("rgen_call") << glu::RaygenSource(updateRayTracingGLSL(css.str())) << buildOptions;
}
{
std::stringstream css;
css <<
"#version 460 core\n"
"#extension GL_EXT_ray_tracing : require\n"
"hitAttributeEXT uvec4 hitValue;\n"
"void main()\n"
"{\n"
" reportIntersectionEXT(0.5f, 0);\n"
"}\n";
programCollection.glslSources.add("isect") << glu::IntersectionSource(updateRayTracingGLSL(css.str())) << buildOptions;
}
{
std::stringstream css;
css <<
"#version 460 core\n"
"#extension GL_EXT_ray_tracing : require\n"
"#extension GL_EXT_ray_query : require\n"
"hitAttributeEXT uvec4 hitValue;\n"
"layout(set = 0, binding = 2) uniform accelerationStructureEXT rqTopLevelAS;\n"
"void main()\n"
"{\n"
" vec3 origin = gl_WorldRayOriginEXT;\n"
" hitValue = uvec4(0,0,0,0);\n" <<
rayQueryTest[m_data.bottomTestType] <<
" reportIntersectionEXT(0.5f, 0);\n"
"}\n";
std::stringstream cssName;
cssName << "isect_" << rayQueryTestName[m_data.bottomTestType];
programCollection.glslSources.add(cssName.str()) << glu::IntersectionSource(updateRayTracingGLSL(css.str())) << buildOptions;
}
{
std::stringstream css;
css <<
"#version 460 core\n"
"#extension GL_EXT_ray_tracing : require\n"
"#extension GL_EXT_ray_query : require\n"
"layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
"layout(set = 0, binding = 2) uniform accelerationStructureEXT rqTopLevelAS;\n"
"void main()\n"
"{\n"
" vec3 origin = gl_WorldRayOriginEXT;\n" <<
rayQueryTest[m_data.bottomTestType] <<
"}\n";
std::stringstream cssName;
cssName << "ahit_" << rayQueryTestName[m_data.bottomTestType];
programCollection.glslSources.add(cssName.str()) << glu::AnyHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
}
{
std::stringstream css;
css <<
"#version 460 core\n"
"#extension GL_EXT_ray_tracing : require\n"
"layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
"void main()\n"
"{\n"
" hitValue.y = 3;\n"
"}\n";
programCollection.glslSources.add("chit") << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
}
{
std::stringstream css;
css <<
"#version 460 core\n"
"#extension GL_EXT_ray_tracing : require\n"
"#extension GL_EXT_ray_query : require\n"
"layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
"layout(set = 0, binding = 2) uniform accelerationStructureEXT rqTopLevelAS;\n"
"void main()\n"
"{\n"
" vec3 origin = gl_WorldRayOriginEXT;\n" <<
rayQueryTest[m_data.bottomTestType] <<
"}\n";
std::stringstream cssName;
cssName << "chit_" << rayQueryTestName[m_data.bottomTestType];
programCollection.glslSources.add(cssName.str()) << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
}
{
std::stringstream css;
css <<
"#version 460 core\n"
"#extension GL_EXT_ray_tracing : require\n"
"layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
"hitAttributeEXT uvec4 hitAttrib;\n"
"void main()\n"
"{\n"
" hitValue = hitAttrib;\n"
"}\n";
programCollection.glslSources.add("chit_isect") << glu::ClosestHitSource(updateRayTracingGLSL(css.str())) << buildOptions;
}
{
std::stringstream css;
css <<
"#version 460 core\n"
"#extension GL_EXT_ray_tracing : require\n"
"layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
"void main()\n"
"{\n"
" hitValue.x = 4;\n"
"}\n";
programCollection.glslSources.add("miss") << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
}
{
std::stringstream css;
css <<
"#version 460 core\n"
"#extension GL_EXT_ray_tracing : require\n"
"#extension GL_EXT_ray_query : require\n"
"layout(location = 0) rayPayloadInEXT uvec4 hitValue;\n"
"layout(set = 0, binding = 2) uniform accelerationStructureEXT rqTopLevelAS;\n"
"void main()\n"
"{\n"
" vec3 origin = gl_WorldRayOriginEXT;\n" <<
rayQueryTest[m_data.bottomTestType] <<
"}\n";
std::stringstream cssName;
cssName << "miss_" << rayQueryTestName[m_data.bottomTestType];
programCollection.glslSources.add(cssName.str()) << glu::MissSource(updateRayTracingGLSL(css.str())) << buildOptions;
}
{
std::stringstream css;
css <<
"#version 460 core\n"
"#extension GL_EXT_ray_tracing : require\n"
"#extension GL_EXT_ray_query : require\n"
"struct CallValue\n{\n"
" vec3 origin;\n"
" uvec4 hitValue;\n"
"};\n"
"layout(location = 0) callableDataInEXT CallValue result;\n"
"layout(set = 0, binding = 2) uniform accelerationStructureEXT rqTopLevelAS;\n"
"void main()\n"
"{\n"
" vec3 origin = result.origin;\n"
" uvec4 hitValue = uvec4(0,0,0,0);\n" <<
rayQueryTest[m_data.bottomTestType] <<
" result.hitValue = hitValue;\n"
"}\n";
std::stringstream cssName;
cssName << "call_" << rayQueryTestName[m_data.bottomTestType];
programCollection.glslSources.add(cssName.str()) << glu::CallableSource(updateRayTracingGLSL(css.str())) << buildOptions;
}
}
}
TestInstance* RayQueryASBasicTestCase::createInstance (Context& context) const
{
return new RayQueryASBasicTestInstance(context, m_data);
}
RayQueryASFuncArgTestCase::RayQueryASFuncArgTestCase (tcu::TestContext& context, const char* name, const char* desc, const TestParams& data)
: RayQueryASBasicTestCase (context, name, desc, data)
{
}
void RayQueryASFuncArgTestCase::initPrograms (SourceCollections& programCollection) const
{
const vk::SpirVAsmBuildOptions spvBuildOptions (programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_4, true);
DE_ASSERT(m_data.shaderSourcePipeline == SSP_COMPUTE_PIPELINE);
DE_ASSERT(m_data.bottomTestType == BTT_TRIANGLES);
// The SPIR-V assembly shader below is based on the following GLSL code.
// In it, rayQueryInitializeBottomWrapper has been modified to take a
// bare AS as the second argument, instead of a pointer.
//
// #version 460 core
// #extension GL_EXT_ray_query : require
// layout(r32ui, set = 0, binding = 0) uniform uimage3D result;
// layout(set = 0, binding = 1) uniform accelerationStructureEXT rqTopLevelAS;
//
// void rayQueryInitializeBottomWrapper(rayQueryEXT rayQuery,
// accelerationStructureEXT topLevel,
// uint rayFlags, uint cullMask, vec3 origin,
// float tMin, vec3 direction, float tMax)
// {
// rayQueryInitializeEXT(rayQuery, topLevel, rayFlags, cullMask, origin, tMin, direction, tMax);
// }
//
// void rayQueryInitializeTopWrapper(rayQueryEXT rayQuery,
// accelerationStructureEXT topLevel,
// uint rayFlags, uint cullMask, vec3 origin,
// float tMin, vec3 direction, float tMax)
// {
// rayQueryInitializeBottomWrapper(rayQuery, topLevel, rayFlags, cullMask, origin, tMin, direction, tMax);
// }
//
// void main()
// {
// vec3 origin = vec3(float(gl_GlobalInvocationID.x) + 0.5, float(gl_GlobalInvocationID.y) + 0.5, 0.5);
// uvec4 hitValue = uvec4(0,0,0,0);
// float tmin = 0.0;
// float tmax = 1.0;
// vec3 direct = vec3(0.0, 0.0, -1.0);
// rayQueryEXT rq;
// rayQueryInitializeTopWrapper(rq, rqTopLevelAS, 0, 0xFF, origin, tmin, direct, tmax);
// if(rayQueryProceedEXT(rq))
// {
// if (rayQueryGetIntersectionTypeEXT(rq, false)==gl_RayQueryCandidateIntersectionTriangleEXT)
// {
// hitValue.y = 1;
// hitValue.x = 1;
// }
// }
// imageStore(result, ivec3(gl_GlobalInvocationID.xy, 0), uvec4(hitValue.x, 0, 0, 0));
// imageStore(result, ivec3(gl_GlobalInvocationID.xy, 1), uvec4(hitValue.y, 0, 0, 0));
// }
std::stringstream css;
css
<< "; SPIR-V\n"
<< "; Version: 1.4\n"
<< "; Generator: Khronos Glslang Reference Front End; 10\n"
<< "; Bound: 139\n"
<< "; Schema: 0\n"
<< "OpCapability Shader\n"
<< "OpCapability RayQueryKHR\n"
<< "OpExtension \"SPV_KHR_ray_query\"\n"
<< "%1 = OpExtInstImport \"GLSL.std.450\"\n"
<< "OpMemoryModel Logical GLSL450\n"
<< "OpEntryPoint GLCompute %4 \"main\" %60 %86 %114\n"
<< "OpExecutionMode %4 LocalSize 1 1 1\n"
<< "OpDecorate %60 BuiltIn GlobalInvocationId\n"
<< "OpDecorate %86 DescriptorSet 0\n"
<< "OpDecorate %86 Binding 1\n"
<< "OpDecorate %114 DescriptorSet 0\n"
<< "OpDecorate %114 Binding 0\n"
<< "%2 = OpTypeVoid\n"
<< "%3 = OpTypeFunction %2\n"
// Bare query type
<< "%6 = OpTypeRayQueryKHR\n"
// Pointer to query.
<< "%7 = OpTypePointer Function %6\n"
// Bare AS type.
<< "%8 = OpTypeAccelerationStructureKHR\n"
// Pointer to AS.
<< "%9 = OpTypePointer UniformConstant %8\n"
<< "%10 = OpTypeInt 32 0\n"
<< "%11 = OpTypePointer Function %10\n"
<< "%12 = OpTypeFloat 32\n"
<< "%13 = OpTypeVector %12 3\n"
<< "%14 = OpTypePointer Function %13\n"
<< "%15 = OpTypePointer Function %12\n"
// This is the function type for rayQueryInitializeTopWrapper and the old rayQueryInitializeBottomWrapper.
<< "%16 = OpTypeFunction %2 %7 %9 %11 %11 %14 %15 %14 %15\n"
// This is the new function type for the modified rayQueryInitializeBottomWrapper that uses a bare AS.
//<< "%16b = OpTypeFunction %2 %6 %8 %11 %11 %14 %15 %14 %15\n"
<< "%16b = OpTypeFunction %2 %7 %8 %11 %11 %14 %15 %14 %15\n"
<< "%58 = OpTypeVector %10 3\n"
<< "%59 = OpTypePointer Input %58\n"
<< "%60 = OpVariable %59 Input\n"
<< "%61 = OpConstant %10 0\n"
<< "%62 = OpTypePointer Input %10\n"
<< "%66 = OpConstant %12 0.5\n"
<< "%68 = OpConstant %10 1\n"
<< "%74 = OpTypeVector %10 4\n"
<< "%75 = OpTypePointer Function %74\n"
<< "%77 = OpConstantComposite %74 %61 %61 %61 %61\n"
<< "%79 = OpConstant %12 0\n"
<< "%81 = OpConstant %12 1\n"
<< "%83 = OpConstant %12 -1\n"
<< "%84 = OpConstantComposite %13 %79 %79 %83\n"
<< "%86 = OpVariable %9 UniformConstant\n"
<< "%87 = OpConstant %10 255\n"
<< "%99 = OpTypeBool\n"
<< "%103 = OpConstantFalse %99\n"
<< "%104 = OpTypeInt 32 1\n"
<< "%105 = OpConstant %104 0\n"
<< "%112 = OpTypeImage %10 3D 0 0 0 2 R32ui\n"
<< "%113 = OpTypePointer UniformConstant %112\n"
<< "%114 = OpVariable %113 UniformConstant\n"
<< "%116 = OpTypeVector %10 2\n"
<< "%119 = OpTypeVector %104 2\n"
<< "%121 = OpTypeVector %104 3\n"
<< "%132 = OpConstant %104 1\n"
// This is main().
<< "%4 = OpFunction %2 None %3\n"
<< "%5 = OpLabel\n"
<< "%57 = OpVariable %14 Function\n"
<< "%76 = OpVariable %75 Function\n"
<< "%78 = OpVariable %15 Function\n"
<< "%80 = OpVariable %15 Function\n"
<< "%82 = OpVariable %14 Function\n"
<< "%85 = OpVariable %7 Function\n"
<< "%88 = OpVariable %11 Function\n"
<< "%89 = OpVariable %11 Function\n"
<< "%90 = OpVariable %14 Function\n"
<< "%92 = OpVariable %15 Function\n"
<< "%94 = OpVariable %14 Function\n"
<< "%96 = OpVariable %15 Function\n"
<< "%63 = OpAccessChain %62 %60 %61\n"
<< "%64 = OpLoad %10 %63\n"
<< "%65 = OpConvertUToF %12 %64\n"
<< "%67 = OpFAdd %12 %65 %66\n"
<< "%69 = OpAccessChain %62 %60 %68\n"
<< "%70 = OpLoad %10 %69\n"
<< "%71 = OpConvertUToF %12 %70\n"
<< "%72 = OpFAdd %12 %71 %66\n"
<< "%73 = OpCompositeConstruct %13 %67 %72 %66\n"
<< "OpStore %57 %73\n"
<< "OpStore %76 %77\n"
<< "OpStore %78 %79\n"
<< "OpStore %80 %81\n"
<< "OpStore %82 %84\n"
<< "OpStore %88 %61\n"
<< "OpStore %89 %87\n"
<< "%91 = OpLoad %13 %57\n"
<< "OpStore %90 %91\n"
<< "%93 = OpLoad %12 %78\n"
<< "OpStore %92 %93\n"
<< "%95 = OpLoad %13 %82\n"
<< "OpStore %94 %95\n"
<< "%97 = OpLoad %12 %80\n"
<< "OpStore %96 %97\n"
<< "%98 = OpFunctionCall %2 %35 %85 %86 %88 %89 %90 %92 %94 %96\n"
<< "%100 = OpRayQueryProceedKHR %99 %85\n"
<< "OpSelectionMerge %102 None\n"
<< "OpBranchConditional %100 %101 %102\n"
<< "%101 = OpLabel\n"
<< "%106 = OpRayQueryGetIntersectionTypeKHR %10 %85 %105\n"
<< "%107 = OpIEqual %99 %106 %61\n"
<< "OpSelectionMerge %109 None\n"
<< "OpBranchConditional %107 %108 %109\n"
<< "%108 = OpLabel\n"
<< "%110 = OpAccessChain %11 %76 %68\n"
<< "OpStore %110 %68\n"
<< "%111 = OpAccessChain %11 %76 %61\n"
<< "OpStore %111 %68\n"
<< "OpBranch %109\n"
<< "%109 = OpLabel\n"
<< "OpBranch %102\n"
<< "%102 = OpLabel\n"
<< "%115 = OpLoad %112 %114\n"
<< "%117 = OpLoad %58 %60\n"
<< "%118 = OpVectorShuffle %116 %117 %117 0 1\n"
<< "%120 = OpBitcast %119 %118\n"
<< "%122 = OpCompositeExtract %104 %120 0\n"
<< "%123 = OpCompositeExtract %104 %120 1\n"
<< "%124 = OpCompositeConstruct %121 %122 %123 %105\n"
<< "%125 = OpAccessChain %11 %76 %61\n"
<< "%126 = OpLoad %10 %125\n"
<< "%127 = OpCompositeConstruct %74 %126 %61 %61 %61\n"
<< "OpImageWrite %115 %124 %127 ZeroExtend\n"
<< "%128 = OpLoad %112 %114\n"
<< "%129 = OpLoad %58 %60\n"
<< "%130 = OpVectorShuffle %116 %129 %129 0 1\n"
<< "%131 = OpBitcast %119 %130\n"
<< "%133 = OpCompositeExtract %104 %131 0\n"
<< "%134 = OpCompositeExtract %104 %131 1\n"
<< "%135 = OpCompositeConstruct %121 %133 %134 %132\n"
<< "%136 = OpAccessChain %11 %76 %68\n"
<< "%137 = OpLoad %10 %136\n"
<< "%138 = OpCompositeConstruct %74 %137 %61 %61 %61\n"
<< "OpImageWrite %128 %135 %138 ZeroExtend\n"
<< "OpReturn\n"
<< "OpFunctionEnd\n"
// This is rayQueryInitializeBottomWrapper, calling OpRayQueryInitializeKHR.
// We have modified the function type so it takes bare arguments.
//%25 = OpFunction %2 None %16
<< "%25 = OpFunction %2 None %16b\n"
// These is the modified parameter.
<< "%17 = OpFunctionParameter %7\n"
//<< "%17 = OpFunctionParameter %6\n"
//%18 = OpFunctionParameter %9
<< "%18 = OpFunctionParameter %8\n"
<< "%19 = OpFunctionParameter %11\n"
<< "%20 = OpFunctionParameter %11\n"
<< "%21 = OpFunctionParameter %14\n"
<< "%22 = OpFunctionParameter %15\n"
<< "%23 = OpFunctionParameter %14\n"
<< "%24 = OpFunctionParameter %15\n"
<< "%26 = OpLabel\n"
// We no longer need to load this parameter.
//%37 = OpLoad %8 %18
<< "%38 = OpLoad %10 %19\n"
<< "%39 = OpLoad %10 %20\n"
<< "%40 = OpLoad %13 %21\n"
<< "%41 = OpLoad %12 %22\n"
<< "%42 = OpLoad %13 %23\n"
<< "%43 = OpLoad %12 %24\n"
// We call OpRayQueryInitializeKHR with bare arguments.
// Note: some experimental lines to pass a bare rayQuery as the first argument have been commented out.
//OpRayQueryInitializeKHR %17 %37 %38 %39 %40 %41 %42 %43
<< "OpRayQueryInitializeKHR %17 %18 %38 %39 %40 %41 %42 %43\n"
<< "OpReturn\n"
<< "OpFunctionEnd\n"
// This is rayQueryInitializeTopWrapper, calling rayQueryInitializeBottomWrapper.
<< "%35 = OpFunction %2 None %16\n"
<< "%27 = OpFunctionParameter %7\n"
<< "%28 = OpFunctionParameter %9\n"
<< "%29 = OpFunctionParameter %11\n"
<< "%30 = OpFunctionParameter %11\n"
<< "%31 = OpFunctionParameter %14\n"
<< "%32 = OpFunctionParameter %15\n"
<< "%33 = OpFunctionParameter %14\n"
<< "%34 = OpFunctionParameter %15\n"
<< "%36 = OpLabel\n"
<< "%44 = OpVariable %11 Function\n"
<< "%46 = OpVariable %11 Function\n"
<< "%48 = OpVariable %14 Function\n"
<< "%50 = OpVariable %15 Function\n"
<< "%52 = OpVariable %14 Function\n"
<< "%54 = OpVariable %15 Function\n"
// We need to load the second argument.
//<< "%27b = OpLoad %6 %27\n"
<< "%28b = OpLoad %8 %28\n"
<< "%45 = OpLoad %10 %29\n"
<< "OpStore %44 %45\n"
<< "%47 = OpLoad %10 %30\n"
<< "OpStore %46 %47\n"
<< "%49 = OpLoad %13 %31\n"
<< "OpStore %48 %49\n"
<< "%51 = OpLoad %12 %32\n"
<< "OpStore %50 %51\n"
<< "%53 = OpLoad %13 %33\n"
<< "OpStore %52 %53\n"
<< "%55 = OpLoad %12 %34\n"
<< "OpStore %54 %55\n"
// We call rayQueryInitializeBottomWrapper with the loaded argument.
//%56 = OpFunctionCall %2 %25 %27 %28 %44 %46 %48 %50 %52 %54
//<< "%56 = OpFunctionCall %2 %25 %27b %28b %44 %46 %48 %50 %52 %54\n"
<< "%56 = OpFunctionCall %2 %25 %27 %28b %44 %46 %48 %50 %52 %54\n"
<< "OpReturn\n"
<< "OpFunctionEnd\n"
;
programCollection.spirvAsmSources.add("comp_as_triangle") << spvBuildOptions << css.str();
}
RayQueryASBasicTestInstance::RayQueryASBasicTestInstance (Context& context, const TestParams& data)
: vkt::TestInstance (context)
, m_data (data)
{
}
RayQueryASBasicTestInstance::~RayQueryASBasicTestInstance (void)
{
}
de::MovePtr<BufferWithMemory> RayQueryASBasicTestInstance::runTest (TestConfiguration* testConfiguration,
SceneBuilder* sceneBuilder,
const deUint32 workerThreadsCount)
{
testConfiguration->initConfiguration(m_context, m_data);
const DeviceInterface& vkd = m_context.getDeviceInterface();
const VkDevice device = m_context.getDevice();
const VkQueue queue = m_context.getUniversalQueue();
Allocator& allocator = m_context.getDefaultAllocator();
const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
const bool htCopy = (workerThreadsCount != 0) && (m_data.operationType == OP_COPY);
const bool htSerialize = (workerThreadsCount != 0) && (m_data.operationType == OP_SERIALIZE);
const VkFormat imageFormat = testConfiguration->getResultImageFormat();
const VkImageCreateInfo imageCreateInfo = makeImageCreateInfo(m_data.width, m_data.height, 2, imageFormat);
const VkImageSubresourceRange imageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
const de::MovePtr<ImageWithMemory> image = de::MovePtr<ImageWithMemory>(new ImageWithMemory(vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any));
const Move<VkImageView> imageView = makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_3D, imageFormat, imageSubresourceRange);
const VkBufferCreateInfo resultBufferCreateInfo = makeBufferCreateInfo(m_data.width * m_data.height * 2 * testConfiguration->getResultImageFormatSize(), VK_BUFFER_USAGE_TRANSFER_DST_BIT);
const VkImageSubresourceLayers resultBufferImageSubresourceLayers = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
const VkBufferImageCopy resultBufferImageRegion = makeBufferImageCopy(makeExtent3D(m_data.width, m_data.height, 2), resultBufferImageSubresourceLayers);
de::MovePtr<BufferWithMemory> resultBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
const VkDescriptorImageInfo resultImageInfo = makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL);
const Move<VkCommandPool> cmdPool = createCommandPool(vkd, device, 0, queueFamilyIndex);
const Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer(vkd, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> bottomLevelAccelerationStructures;
de::MovePtr<TopLevelAccelerationStructure> topLevelAccelerationStructure;
std::vector<de::SharedPtr<BottomLevelAccelerationStructure>> bottomLevelAccelerationStructureCopies;
de::MovePtr<TopLevelAccelerationStructure> topLevelAccelerationStructureCopy;
std::vector<de::SharedPtr<SerialStorage>> bottomSerialized;
std::vector<de::SharedPtr<SerialStorage>> topSerialized;
std::vector<VkDeviceSize> accelerationCompactedSizes;
std::vector<VkDeviceSize> accelerationSerialSizes;
Move<VkQueryPool> m_queryPoolCompact;
Move<VkQueryPool> m_queryPoolSerial;
beginCommandBuffer(vkd, *cmdBuffer, 0u);
{
const VkImageMemoryBarrier preImageBarrier = makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT,
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
**image, imageSubresourceRange);
cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &preImageBarrier);
const VkClearValue clearValue = testConfiguration->getClearValue();
vkd.cmdClearColorImage(*cmdBuffer, **image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1, &imageSubresourceRange);
const VkImageMemoryBarrier postImageBarrier = makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL,
**image, imageSubresourceRange);
cmdPipelineImageMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, &postImageBarrier);
// build bottom level acceleration structures and their copies ( only when we are testing copying bottom level acceleration structures )
bool bottomCompact = m_data.operationType == OP_COMPACT && m_data.operationTarget == OT_BOTTOM_ACCELERATION;
bool bottomSerial = m_data.operationType == OP_SERIALIZE && m_data.operationTarget == OT_BOTTOM_ACCELERATION;
const bool buildWithoutGeom = (m_data.emptyASCase == EmptyAccelerationStructureCase::NO_GEOMETRIES_BOTTOM);
const bool bottomNoPrimitives = (m_data.emptyASCase == EmptyAccelerationStructureCase::NO_PRIMITIVES_BOTTOM);
const bool topNoPrimitives = (m_data.emptyASCase == EmptyAccelerationStructureCase::NO_PRIMITIVES_TOP);
const bool inactiveInstances = (m_data.emptyASCase == EmptyAccelerationStructureCase::INACTIVE_INSTANCES);
bottomLevelAccelerationStructures = sceneBuilder->initBottomAccelerationStructures(m_context, m_data);
VkBuildAccelerationStructureFlagsKHR allowCompactionFlag = VK_BUILD_ACCELERATION_STRUCTURE_ALLOW_COMPACTION_BIT_KHR;
VkBuildAccelerationStructureFlagsKHR emptyCompactionFlag = VkBuildAccelerationStructureFlagsKHR(0);
VkBuildAccelerationStructureFlagsKHR bottomCompactFlags = (bottomCompact ? allowCompactionFlag : emptyCompactionFlag);
VkBuildAccelerationStructureFlagsKHR bottomBuildFlags = m_data.buildFlags | bottomCompactFlags;
std::vector<VkAccelerationStructureKHR> accelerationStructureHandles;
std::vector<VkDeviceSize> bottomBlasCompactSize;
std::vector<VkDeviceSize> bottomBlasSerialSize;
for (auto& blas : bottomLevelAccelerationStructures)
{
blas->setBuildType (m_data.buildType);
blas->setBuildFlags (bottomBuildFlags);
blas->setUseArrayOfPointers (m_data.bottomUsesAOP);
blas->setCreateGeneric (m_data.bottomGeneric);
blas->setBuildWithoutGeometries (buildWithoutGeom);
blas->setBuildWithoutPrimitives (bottomNoPrimitives);
blas->createAndBuild (vkd, device, *cmdBuffer, allocator);
accelerationStructureHandles.push_back (*(blas->getPtr()));
}
if (m_data.operationType == OP_COMPACT)
{
deUint32 queryCount = (m_data.operationTarget == OT_BOTTOM_ACCELERATION) ? deUint32(bottomLevelAccelerationStructures.size()) : 1u;
if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
m_queryPoolCompact = makeQueryPool(vkd, device, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, queryCount);
if (m_data.operationTarget == OT_BOTTOM_ACCELERATION)
queryAccelerationStructureSize(vkd, device, *cmdBuffer, accelerationStructureHandles, m_data.buildType, m_queryPoolCompact.get(), VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, 0u, bottomBlasCompactSize);
}
if (m_data.operationType == OP_SERIALIZE)
{
deUint32 queryCount = (m_data.operationTarget == OT_BOTTOM_ACCELERATION) ? deUint32(bottomLevelAccelerationStructures.size()) : 1u;
if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
m_queryPoolSerial = makeQueryPool(vkd, device, VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, queryCount);
if (m_data.operationTarget == OT_BOTTOM_ACCELERATION)
queryAccelerationStructureSize(vkd, device, *cmdBuffer, accelerationStructureHandles, m_data.buildType, m_queryPoolSerial.get(), VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, 0u, bottomBlasSerialSize);
}
// if AS is built on GPU and we are planning to make a compact copy of it or serialize / deserialize it - we have to have download query results to CPU
if ((m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) && (bottomCompact || bottomSerial))
{
endCommandBuffer(vkd, *cmdBuffer);
submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
if (bottomCompact)
VK_CHECK(vkd.getQueryPoolResults(device, *m_queryPoolCompact, 0u, deUint32(bottomBlasCompactSize.size()), sizeof(VkDeviceSize) * bottomBlasCompactSize.size(), bottomBlasCompactSize.data(), sizeof(VkDeviceSize), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
if (bottomSerial)
VK_CHECK(vkd.getQueryPoolResults(device, *m_queryPoolSerial, 0u, deUint32(bottomBlasSerialSize.size()), sizeof(VkDeviceSize) * bottomBlasSerialSize.size(), bottomBlasSerialSize.data(), sizeof(VkDeviceSize), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
beginCommandBuffer(vkd, *cmdBuffer, 0u);
}
auto bottomLevelAccelerationStructuresPtr = &bottomLevelAccelerationStructures;
if (m_data.operationType != OP_NONE && m_data.operationTarget == OT_BOTTOM_ACCELERATION)
{
switch (m_data.operationType)
{
case OP_COPY:
{
for (size_t i = 0; i < bottomLevelAccelerationStructures.size(); ++i)
{
de::MovePtr<BottomLevelAccelerationStructure> asCopy = makeBottomLevelAccelerationStructure();
asCopy->setDeferredOperation(htCopy, workerThreadsCount);
asCopy->setBuildType(m_data.buildType);
asCopy->setBuildFlags(m_data.buildFlags);
asCopy->setUseArrayOfPointers(m_data.bottomUsesAOP);
asCopy->setCreateGeneric(m_data.bottomGeneric);
asCopy->setBuildWithoutGeometries(buildWithoutGeom);
asCopy->setBuildWithoutPrimitives(bottomNoPrimitives);
asCopy->createAndCopyFrom(vkd, device, *cmdBuffer, allocator, bottomLevelAccelerationStructures[i].get(), 0u, 0u);
bottomLevelAccelerationStructureCopies.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(asCopy.release()));
}
break;
}
case OP_COMPACT:
{
for (size_t i = 0; i < bottomLevelAccelerationStructures.size(); ++i)
{
de::MovePtr<BottomLevelAccelerationStructure> asCopy = makeBottomLevelAccelerationStructure();
asCopy->setBuildType(m_data.buildType);
asCopy->setBuildFlags(m_data.buildFlags);
asCopy->setUseArrayOfPointers(m_data.bottomUsesAOP);
asCopy->setCreateGeneric(m_data.bottomGeneric);
asCopy->setBuildWithoutGeometries(buildWithoutGeom);
asCopy->setBuildWithoutPrimitives(bottomNoPrimitives);
asCopy->createAndCopyFrom(vkd, device, *cmdBuffer, allocator, bottomLevelAccelerationStructures[i].get(), bottomBlasCompactSize[i], 0u);
bottomLevelAccelerationStructureCopies.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(asCopy.release()));
}
break;
}
case OP_SERIALIZE:
{
for (size_t i = 0; i < bottomLevelAccelerationStructures.size(); ++i)
{
de::SharedPtr<SerialStorage> storage(new SerialStorage(vkd, device, allocator, m_data.buildType, bottomBlasSerialSize[i]));
bottomLevelAccelerationStructures[i]->setDeferredOperation(htSerialize, workerThreadsCount);
bottomLevelAccelerationStructures[i]->serialize(vkd, device, *cmdBuffer, storage.get());
bottomSerialized.push_back(storage);
if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
{
endCommandBuffer(vkd, *cmdBuffer);
submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
beginCommandBuffer(vkd, *cmdBuffer, 0u);
}
de::MovePtr<BottomLevelAccelerationStructure> asCopy = makeBottomLevelAccelerationStructure();
asCopy->setBuildType(m_data.buildType);
asCopy->setBuildFlags(m_data.buildFlags);
asCopy->setUseArrayOfPointers(m_data.bottomUsesAOP);
asCopy->setCreateGeneric(m_data.bottomGeneric);
asCopy->setBuildWithoutGeometries(buildWithoutGeom);
asCopy->setBuildWithoutPrimitives(bottomNoPrimitives);
asCopy->setDeferredOperation(htSerialize, workerThreadsCount);
asCopy->createAndDeserializeFrom(vkd, device, *cmdBuffer, allocator, storage.get(), 0u);
bottomLevelAccelerationStructureCopies.push_back(de::SharedPtr<BottomLevelAccelerationStructure>(asCopy.release()));
}
break;
}
default:
DE_ASSERT(DE_FALSE);
}
bottomLevelAccelerationStructuresPtr = &bottomLevelAccelerationStructureCopies;
}
// build top level acceleration structures and their copies ( only when we are testing copying top level acceleration structures )
bool topCompact = m_data.operationType == OP_COMPACT && m_data.operationTarget == OT_TOP_ACCELERATION;
bool topSerial = m_data.operationType == OP_SERIALIZE && m_data.operationTarget == OT_TOP_ACCELERATION;
VkBuildAccelerationStructureFlagsKHR topCompactFlags = (topCompact ? allowCompactionFlag : emptyCompactionFlag);
VkBuildAccelerationStructureFlagsKHR topBuildFlags = m_data.buildFlags | topCompactFlags;
std::vector<VkAccelerationStructureKHR> topLevelStructureHandles;
std::vector<VkDeviceSize> topBlasCompactSize;
std::vector<VkDeviceSize> topBlasSerialSize;
topLevelAccelerationStructure = sceneBuilder->initTopAccelerationStructure(m_context, m_data, *bottomLevelAccelerationStructuresPtr);
topLevelAccelerationStructure->setBuildType (m_data.buildType);
topLevelAccelerationStructure->setBuildFlags (topBuildFlags);
topLevelAccelerationStructure->setBuildWithoutPrimitives (topNoPrimitives);
topLevelAccelerationStructure->setUseArrayOfPointers (m_data.topUsesAOP);
topLevelAccelerationStructure->setCreateGeneric (m_data.topGeneric);
topLevelAccelerationStructure->setInactiveInstances (inactiveInstances);
topLevelAccelerationStructure->createAndBuild (vkd, device, *cmdBuffer, allocator);
topLevelStructureHandles.push_back (*(topLevelAccelerationStructure->getPtr()));
if (topCompact)
queryAccelerationStructureSize(vkd, device, *cmdBuffer, topLevelStructureHandles, m_data.buildType, m_queryPoolCompact.get(), VK_QUERY_TYPE_ACCELERATION_STRUCTURE_COMPACTED_SIZE_KHR, 0u, topBlasCompactSize);
if (topSerial)
queryAccelerationStructureSize(vkd, device, *cmdBuffer, topLevelStructureHandles, m_data.buildType, m_queryPoolSerial.get(), VK_QUERY_TYPE_ACCELERATION_STRUCTURE_SERIALIZATION_SIZE_KHR, 0u, topBlasSerialSize);
// if AS is built on GPU and we are planning to make a compact copy of it or serialize / deserialize it - we have to have download query results to CPU
if ((m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR) && (topCompact || topSerial))
{
endCommandBuffer(vkd, *cmdBuffer);
submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
if (topCompact)
VK_CHECK(vkd.getQueryPoolResults(device, *m_queryPoolCompact, 0u, deUint32(topBlasCompactSize.size()), sizeof(VkDeviceSize) * topBlasCompactSize.size(), topBlasCompactSize.data(), sizeof(VkDeviceSize), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
if (topSerial)
VK_CHECK(vkd.getQueryPoolResults(device, *m_queryPoolSerial, 0u, deUint32(topBlasSerialSize.size()), sizeof(VkDeviceSize) * topBlasSerialSize.size(), topBlasSerialSize.data(), sizeof(VkDeviceSize), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
beginCommandBuffer(vkd, *cmdBuffer, 0u);
}
const TopLevelAccelerationStructure* topLevelRayTracedPtr = topLevelAccelerationStructure.get();
if (m_data.operationType != OP_NONE && m_data.operationTarget == OT_TOP_ACCELERATION)
{
switch (m_data.operationType)
{
case OP_COPY:
{
topLevelAccelerationStructureCopy = makeTopLevelAccelerationStructure();
topLevelAccelerationStructureCopy->setDeferredOperation(htCopy, workerThreadsCount);
topLevelAccelerationStructureCopy->setBuildType(m_data.buildType);
topLevelAccelerationStructureCopy->setBuildFlags(m_data.buildFlags);
topLevelAccelerationStructureCopy->setBuildWithoutPrimitives(topNoPrimitives);
topLevelAccelerationStructureCopy->setInactiveInstances(inactiveInstances);
topLevelAccelerationStructureCopy->setUseArrayOfPointers(m_data.topUsesAOP);
topLevelAccelerationStructureCopy->setCreateGeneric(m_data.topGeneric);
topLevelAccelerationStructureCopy->createAndCopyFrom(vkd, device, *cmdBuffer, allocator, topLevelAccelerationStructure.get(), 0u, 0u);
break;
}
case OP_COMPACT:
{
topLevelAccelerationStructureCopy = makeTopLevelAccelerationStructure();
topLevelAccelerationStructureCopy->setBuildType(m_data.buildType);
topLevelAccelerationStructureCopy->setBuildFlags(m_data.buildFlags);
topLevelAccelerationStructureCopy->setBuildWithoutPrimitives(topNoPrimitives);
topLevelAccelerationStructureCopy->setInactiveInstances(inactiveInstances);
topLevelAccelerationStructureCopy->setUseArrayOfPointers(m_data.topUsesAOP);
topLevelAccelerationStructureCopy->setCreateGeneric(m_data.topGeneric);
topLevelAccelerationStructureCopy->createAndCopyFrom(vkd, device, *cmdBuffer, allocator, topLevelAccelerationStructure.get(), topBlasCompactSize[0], 0u);
break;
}
case OP_SERIALIZE:
{
de::SharedPtr<SerialStorage> storage(new SerialStorage(vkd, device, allocator, m_data.buildType, topBlasSerialSize[0]));
topLevelAccelerationStructure->setDeferredOperation(htSerialize, workerThreadsCount);
topLevelAccelerationStructure->serialize(vkd, device, *cmdBuffer, storage.get());
topSerialized.push_back(storage);
if (m_data.buildType == VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR)
{
endCommandBuffer(vkd, *cmdBuffer);
submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
vkd.resetCommandPool(device, *cmdPool, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
beginCommandBuffer(vkd, *cmdBuffer, 0u);
}
topLevelAccelerationStructureCopy = makeTopLevelAccelerationStructure();
topLevelAccelerationStructureCopy->setBuildType(m_data.buildType);
topLevelAccelerationStructureCopy->setBuildFlags(m_data.buildFlags);
topLevelAccelerationStructureCopy->setBuildWithoutPrimitives(topNoPrimitives);
topLevelAccelerationStructureCopy->setInactiveInstances(inactiveInstances);
topLevelAccelerationStructureCopy->setUseArrayOfPointers(m_data.topUsesAOP);
topLevelAccelerationStructureCopy->setCreateGeneric(m_data.topGeneric);
topLevelAccelerationStructureCopy->setDeferredOperation(htSerialize, workerThreadsCount);
topLevelAccelerationStructureCopy->createAndDeserializeFrom(vkd, device, *cmdBuffer, allocator, storage.get(), 0u);
break;
}
default:
DE_ASSERT(DE_FALSE);
}
topLevelRayTracedPtr = topLevelAccelerationStructureCopy.get();
}
const VkMemoryBarrier preTraceMemoryBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT);
cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, &preTraceMemoryBarrier);
VkWriteDescriptorSetAccelerationStructureKHR accelerationStructureWriteDescriptorSet =
{
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR, // VkStructureType sType;
DE_NULL, // const void* pNext;
1u, // deUint32 accelerationStructureCount;
topLevelRayTracedPtr->getPtr(), // const VkAccelerationStructureKHR* pAccelerationStructures;
};
testConfiguration->fillCommandBuffer(m_context, m_data, *cmdBuffer, accelerationStructureWriteDescriptorSet, resultImageInfo);
const VkMemoryBarrier postTestMemoryBarrier = makeMemoryBarrier(VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT);
const VkMemoryBarrier postCopyMemoryBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, &postTestMemoryBarrier);
vkd.cmdCopyImageToBuffer(*cmdBuffer, **image, VK_IMAGE_LAYOUT_GENERAL, **resultBuffer, 1u, &resultBufferImageRegion);
cmdPipelineMemoryBarrier(vkd, *cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &postCopyMemoryBarrier);
}
endCommandBuffer(vkd, *cmdBuffer);
submitCommandsAndWait(vkd, device, queue, cmdBuffer.get());
invalidateMappedMemoryRange(vkd, device, resultBuffer->getAllocation().getMemory(), resultBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
return resultBuffer;
}
bool RayQueryASBasicTestInstance::iterateNoWorkers (void)
{
de::SharedPtr<TestConfiguration> testConfiguration = createTestConfiguration(m_data.shaderSourcePipeline);
de::SharedPtr<SceneBuilder> sceneBuilder = de::SharedPtr<SceneBuilder>(new CheckerboardSceneBuilder());
const de::MovePtr<BufferWithMemory> buffer = runTest(testConfiguration.get(), sceneBuilder.get(), 0);
return testConfiguration->verifyImage(buffer.get(), m_context, m_data);