diff --git a/jsonGenLayerTests/GoldenJsonFiles/JSON_GEN_LAYER_TESTS_pipeline_0.json b/jsonGenLayerTests/GoldenJsonFiles/JSON_GEN_LAYER_TESTS_pipeline_0.json index bf5c943347..aa71059e1c 100755 --- a/jsonGenLayerTests/GoldenJsonFiles/JSON_GEN_LAYER_TESTS_pipeline_0.json +++ b/jsonGenLayerTests/GoldenJsonFiles/JSON_GEN_LAYER_TESTS_pipeline_0.json @@ -1,7 +1,7 @@ { "GraphicsPipelineState" : { - "Renderpass" : + "Renderpass" : { "sType" : "VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO", "pNext":"NULL", @@ -54,26 +54,99 @@ "YcbcrSamplers" : [ + { + "1000" : + { + "sType" : "VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO", + "pNext":"NULL", + "format" : "VK_FORMAT_G8_B8R8_2PLANE_420_UNORM", + "ycbcrModel" : "VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709", + "ycbcrRange" : "VK_SAMPLER_YCBCR_RANGE_ITU_FULL", + "components": + { + "r" : "VK_COMPONENT_SWIZZLE_IDENTITY", + "g" : "VK_COMPONENT_SWIZZLE_IDENTITY", + "b" : "VK_COMPONENT_SWIZZLE_IDENTITY", + "a" : "VK_COMPONENT_SWIZZLE_IDENTITY" + }, + "xChromaOffset" : "VK_CHROMA_LOCATION_COSITED_EVEN", + "yChromaOffset" : "VK_CHROMA_LOCATION_COSITED_EVEN", + "chromaFilter" : "VK_FILTER_NEAREST", + "forceExplicitReconstruction" : "VK_FALSE" + } + } ], "ImmutableSamplers" : [ + { + "pImmutableSamplers_0_0" : + { + "sType" : "VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO", + "pNext": + { + "sType" : "VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO", + "pNext":"NULL", + "conversion" : 1000 + }, + "flags" : "0", + "magFilter" : "VK_FILTER_LINEAR", + "minFilter" : "VK_FILTER_LINEAR", + "mipmapMode" : "VK_SAMPLER_MIPMAP_MODE_LINEAR", + "addressModeU" : "VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE", + "addressModeV" : "VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE", + "addressModeW" : "VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE", + "mipLodBias" : 0, + "anisotropyEnable" : "VK_FALSE", + "maxAnisotropy" : 0, + "compareEnable" : "VK_FALSE", + "compareOp" : "VK_COMPARE_OP_NEVER", + "minLod" : 0, + "maxLod" : 0, + "borderColor" : "VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK", + "unnormalizedCoordinates" : "VK_FALSE" + } + } ], "DescriptorSetLayouts" : [ + { + "pSetLayouts_0": + { + "sType" : "VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO", + "pNext":"NULL", + "flags" : "0", + "bindingCount" : 1, + "pBindings": + [ + { + "binding" : 0, + "descriptorType" : "VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER", + "descriptorCount" : 1, + "stageFlags" : "VK_SHADER_STAGE_FRAGMENT_BIT", + "pImmutableSamplers": + [ + "pImmutableSamplers_0_0" + ] + } + ] + } + } ], - "PipelineLayout" : + "PipelineLayout" : { "sType" : "VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO", "pNext":"NULL", "flags" : 0, - "setLayoutCount" : 0, + "setLayoutCount" : 1, "pSetLayouts": - "NULL", + [ + "pSetLayouts_0" + ], "pushConstantRangeCount" : 0, "pPushConstantRanges": "NULL" }, - "GraphicsPipeline" : + "GraphicsPipeline" : { "sType" : "VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO", "pNext":"NULL", @@ -214,28 +287,96 @@ "stage" : "VK_SHADER_STAGE_FRAGMENT_BIT", "filename" : "JSON_GEN_LAYER_TESTS_pipeline_0.frag.spv" } - ] + ], + "PhysicalDeviceFeatures" : + { + "sType" : "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2", + "pNext": + { + "sType" : "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES", + "pNext":"NULL", + "samplerYcbcrConversion" : "VK_TRUE" + }, + "features": + { + "robustBufferAccess" : "VK_TRUE", + "fullDrawIndexUint32" : "VK_TRUE", + "imageCubeArray" : "VK_TRUE", + "independentBlend" : "VK_TRUE", + "geometryShader" : "VK_TRUE", + "tessellationShader" : "VK_TRUE", + "sampleRateShading" : "VK_TRUE", + "dualSrcBlend" : "VK_TRUE", + "logicOp" : "VK_TRUE", + "multiDrawIndirect" : "VK_TRUE", + "drawIndirectFirstInstance" : "VK_TRUE", + "depthClamp" : "VK_TRUE", + "depthBiasClamp" : "VK_TRUE", + "fillModeNonSolid" : "VK_TRUE", + "depthBounds" : "VK_TRUE", + "wideLines" : "VK_TRUE", + "largePoints" : "VK_TRUE", + "alphaToOne" : "VK_TRUE", + "multiViewport" : "VK_TRUE", + "samplerAnisotropy" : "VK_TRUE", + "textureCompressionETC2" : "VK_FALSE", + "textureCompressionASTC_LDR" : "VK_FALSE", + "textureCompressionBC" : "VK_TRUE", + "occlusionQueryPrecise" : "VK_TRUE", + "pipelineStatisticsQuery" : "VK_TRUE", + "vertexPipelineStoresAndAtomics" : "VK_TRUE", + "fragmentStoresAndAtomics" : "VK_TRUE", + "shaderTessellationAndGeometryPointSize" : "VK_TRUE", + "shaderImageGatherExtended" : "VK_TRUE", + "shaderStorageImageExtendedFormats" : "VK_TRUE", + "shaderStorageImageMultisample" : "VK_TRUE", + "shaderStorageImageReadWithoutFormat" : "VK_TRUE", + "shaderStorageImageWriteWithoutFormat" : "VK_TRUE", + "shaderUniformBufferArrayDynamicIndexing" : "VK_TRUE", + "shaderSampledImageArrayDynamicIndexing" : "VK_TRUE", + "shaderStorageBufferArrayDynamicIndexing" : "VK_TRUE", + "shaderStorageImageArrayDynamicIndexing" : "VK_TRUE", + "shaderClipDistance" : "VK_TRUE", + "shaderCullDistance" : "VK_TRUE", + "shaderFloat64" : "VK_TRUE", + "shaderInt64" : "VK_TRUE", + "shaderInt16" : "VK_TRUE", + "shaderResourceResidency" : "VK_TRUE", + "shaderResourceMinLod" : "VK_TRUE", + "sparseBinding" : "VK_TRUE", + "sparseResidencyBuffer" : "VK_TRUE", + "sparseResidencyImage2D" : "VK_TRUE", + "sparseResidencyImage3D" : "VK_TRUE", + "sparseResidency2Samples" : "VK_TRUE", + "sparseResidency4Samples" : "VK_TRUE", + "sparseResidency8Samples" : "VK_TRUE", + "sparseResidency16Samples" : "VK_TRUE", + "sparseResidencyAliased" : "VK_TRUE", + "variableMultisampleRate" : "VK_TRUE", + "inheritedQueries" : "VK_TRUE" + } + }, }, - "EnabledExtensions" : + "EnabledExtensions" : [ ], - "PipelineUUID" : + "PipelineUUID" : [ - 119, - 108, - 254, - 154, + 44, + 238, + 130, + 31, + 216, + 20, + 150, 61, - 91, - 217, - 72, - 164, - 186, - 245, - 99, - 244, + 25, + 55, + 80, 243, - 84, - 164 + 36, + 85, + 205, + 44 ] } diff --git a/jsonGenLayerTests/GoldenJsonFiles/JSON_GEN_LAYER_TESTS_pipeline_1.json b/jsonGenLayerTests/GoldenJsonFiles/JSON_GEN_LAYER_TESTS_pipeline_1.json index 5305fc2565..4d96ae0bcf 100755 --- a/jsonGenLayerTests/GoldenJsonFiles/JSON_GEN_LAYER_TESTS_pipeline_1.json +++ b/jsonGenLayerTests/GoldenJsonFiles/JSON_GEN_LAYER_TESTS_pipeline_1.json @@ -3,9 +3,58 @@ { "YcbcrSamplers" : [ + { + "1000" : + { + "sType" : "VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO", + "pNext":"NULL", + "format" : "VK_FORMAT_G8_B8R8_2PLANE_420_UNORM", + "ycbcrModel" : "VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709", + "ycbcrRange" : "VK_SAMPLER_YCBCR_RANGE_ITU_FULL", + "components": + { + "r" : "VK_COMPONENT_SWIZZLE_IDENTITY", + "g" : "VK_COMPONENT_SWIZZLE_IDENTITY", + "b" : "VK_COMPONENT_SWIZZLE_IDENTITY", + "a" : "VK_COMPONENT_SWIZZLE_IDENTITY" + }, + "xChromaOffset" : "VK_CHROMA_LOCATION_COSITED_EVEN", + "yChromaOffset" : "VK_CHROMA_LOCATION_COSITED_EVEN", + "chromaFilter" : "VK_FILTER_NEAREST", + "forceExplicitReconstruction" : "VK_FALSE" + } + } ], "ImmutableSamplers" : [ + { + "pImmutableSamplers_0_0" : + { + "sType" : "VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO", + "pNext": + { + "sType" : "VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO", + "pNext":"NULL", + "conversion" : 1000 + }, + "flags" : "0", + "magFilter" : "VK_FILTER_LINEAR", + "minFilter" : "VK_FILTER_LINEAR", + "mipmapMode" : "VK_SAMPLER_MIPMAP_MODE_LINEAR", + "addressModeU" : "VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE", + "addressModeV" : "VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE", + "addressModeW" : "VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE", + "mipLodBias" : 0, + "anisotropyEnable" : "VK_FALSE", + "maxAnisotropy" : 0, + "compareEnable" : "VK_FALSE", + "compareOp" : "VK_COMPARE_OP_NEVER", + "minLod" : 0, + "maxLod" : 0, + "borderColor" : "VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK", + "unnormalizedCoordinates" : "VK_FALSE" + } + } ], "DescriptorSetLayouts" : [ @@ -15,7 +64,7 @@ "sType" : "VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO", "pNext":"NULL", "flags" : "0", - "bindingCount" : 1, + "bindingCount" : 2, "pBindings": [ { @@ -25,12 +74,22 @@ "stageFlags" : "VK_SHADER_STAGE_COMPUTE_BIT", "pImmutableSamplers": "NULL" + }, + { + "binding" : 1, + "descriptorType" : "VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER", + "descriptorCount" : 1, + "stageFlags" : "VK_SHADER_STAGE_COMPUTE_BIT", + "pImmutableSamplers": + [ + "pImmutableSamplers_1_0" + ] } ] } } ], - "PipelineLayout" : + "PipelineLayout" : { "sType" : "VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO", "pNext":"NULL", @@ -44,7 +103,7 @@ "pPushConstantRanges": "NULL" }, - "ComputePipeline" : + "ComputePipeline" : { "sType" : "VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO", "pNext":"NULL", @@ -70,28 +129,96 @@ "stage" : "VK_SHADER_STAGE_COMPUTE_BIT", "filename" : "JSON_GEN_LAYER_TESTS_pipeline_1.compute.spv" } - ] + ], + "PhysicalDeviceFeatures" : + { + "sType" : "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2", + "pNext": + { + "sType" : "VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES", + "pNext":"NULL", + "samplerYcbcrConversion" : "VK_TRUE" + }, + "features": + { + "robustBufferAccess" : "VK_TRUE", + "fullDrawIndexUint32" : "VK_TRUE", + "imageCubeArray" : "VK_TRUE", + "independentBlend" : "VK_TRUE", + "geometryShader" : "VK_TRUE", + "tessellationShader" : "VK_TRUE", + "sampleRateShading" : "VK_TRUE", + "dualSrcBlend" : "VK_TRUE", + "logicOp" : "VK_TRUE", + "multiDrawIndirect" : "VK_TRUE", + "drawIndirectFirstInstance" : "VK_TRUE", + "depthClamp" : "VK_TRUE", + "depthBiasClamp" : "VK_TRUE", + "fillModeNonSolid" : "VK_TRUE", + "depthBounds" : "VK_TRUE", + "wideLines" : "VK_TRUE", + "largePoints" : "VK_TRUE", + "alphaToOne" : "VK_TRUE", + "multiViewport" : "VK_TRUE", + "samplerAnisotropy" : "VK_TRUE", + "textureCompressionETC2" : "VK_FALSE", + "textureCompressionASTC_LDR" : "VK_FALSE", + "textureCompressionBC" : "VK_TRUE", + "occlusionQueryPrecise" : "VK_TRUE", + "pipelineStatisticsQuery" : "VK_TRUE", + "vertexPipelineStoresAndAtomics" : "VK_TRUE", + "fragmentStoresAndAtomics" : "VK_TRUE", + "shaderTessellationAndGeometryPointSize" : "VK_TRUE", + "shaderImageGatherExtended" : "VK_TRUE", + "shaderStorageImageExtendedFormats" : "VK_TRUE", + "shaderStorageImageMultisample" : "VK_TRUE", + "shaderStorageImageReadWithoutFormat" : "VK_TRUE", + "shaderStorageImageWriteWithoutFormat" : "VK_TRUE", + "shaderUniformBufferArrayDynamicIndexing" : "VK_TRUE", + "shaderSampledImageArrayDynamicIndexing" : "VK_TRUE", + "shaderStorageBufferArrayDynamicIndexing" : "VK_TRUE", + "shaderStorageImageArrayDynamicIndexing" : "VK_TRUE", + "shaderClipDistance" : "VK_TRUE", + "shaderCullDistance" : "VK_TRUE", + "shaderFloat64" : "VK_TRUE", + "shaderInt64" : "VK_TRUE", + "shaderInt16" : "VK_TRUE", + "shaderResourceResidency" : "VK_TRUE", + "shaderResourceMinLod" : "VK_TRUE", + "sparseBinding" : "VK_TRUE", + "sparseResidencyBuffer" : "VK_TRUE", + "sparseResidencyImage2D" : "VK_TRUE", + "sparseResidencyImage3D" : "VK_TRUE", + "sparseResidency2Samples" : "VK_TRUE", + "sparseResidency4Samples" : "VK_TRUE", + "sparseResidency8Samples" : "VK_TRUE", + "sparseResidency16Samples" : "VK_TRUE", + "sparseResidencyAliased" : "VK_TRUE", + "variableMultisampleRate" : "VK_TRUE", + "inheritedQueries" : "VK_TRUE" + } + }, }, - "EnabledExtensions" : + "EnabledExtensions" : [ ], - "PipelineUUID" : + "PipelineUUID" : [ - 32, - 6, - 226, - 50, - 19, - 74, - 246, - 232, - 54, - 124, - 197, - 163, - 80, - 127, - 246, - 209 + 207, + 93, + 164, + 115, + 0, + 107, + 159, + 2, + 31, + 219, + 70, + 31, + 52, + 106, + 40, + 23 ] } diff --git a/jsonGenLayerTests/main.cpp b/jsonGenLayerTests/main.cpp index cbac5b5c7f..abf0e2b9ac 100755 --- a/jsonGenLayerTests/main.cpp +++ b/jsonGenLayerTests/main.cpp @@ -49,43 +49,46 @@ static VkPipelineShaderStageCreateInfo globalShaderStageInfo[3] = { { }, { }, { static VkFormat globalColorFormat = VK_FORMAT_B8G8R8A8_UNORM; static int globalWidth = 1920; static int globalHeight = 1080; +static VkSamplerYcbcrConversion globalYcbcrConversion = VK_NULL_HANDLE; +static VkSampler globalYcbcrSampler = VK_NULL_HANDLE; int globalUUIDGraphicsPipeline[] = { - 119, - 108, - 254, - 154, + 44, + 238, + 130, + 31, + 216, + 20, + 150, 61, - 91, - 217, - 72, - 164, - 186, - 245, - 99, - 244, + 25, + 55, + 80, 243, - 84, - 164 + 36, + 85, + 205, + 44 }; int globalUUIDComputePipeline[] = { - 32, - 6, - 226, - 50, - 19, - 74, - 246, - 232, - 54, - 124, - 197, - 163, - 80, - 127, - 246, - 209 + 207, + 93, + 164, + 115, + 0, + 107, + 159, + 2, + 31, + 219, + 70, + 31, + 52, + 106, + 40, + 23 }; static VkDescriptorSetLayout globalDescriptorSetLayout = VK_NULL_HANDLE; +static VkDescriptorSetLayout globalGraphicsDescriptorSetLayout = VK_NULL_HANDLE; #define LOG(fn) if (result == VK_SUCCESS) std::cout << fn << " OK" << std::endl; \ else std::cout << fn << " ERROR!!" << std::endl; \ @@ -115,10 +118,19 @@ VkResult createInstance() result = checkValidationLayerSupport(); LOG("checkValidationLayerSupport"); - //Create a Vulkan instance + //Create a Vulkan instance with VkApplicationInfo for Vulkan 1.1 (needed for YCbCr support) + VkApplicationInfo appInfo = {}; + appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + appInfo.pNext = nullptr; + appInfo.pApplicationName = "JsonGenLayerTests"; + appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); + appInfo.pEngineName = "JsonGenLayerTests"; + appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); + appInfo.apiVersion = VK_API_VERSION_1_1; // Use Vulkan 1.1 for YCbCr support + VkInstanceCreateInfo instanceCreateInfo = {}; instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; - instanceCreateInfo.pApplicationInfo = NULL; + instanceCreateInfo.pApplicationInfo = &appInfo; instanceCreateInfo.enabledExtensionCount = 0; instanceCreateInfo.ppEnabledExtensionNames = NULL; @@ -157,7 +169,7 @@ VkResult selectPhysicalDevice() assert(result == VK_SUCCESS); vkGetPhysicalDeviceProperties(globalPhysdevs[0], &globalDeviceProperties); - + return result; } @@ -263,6 +275,17 @@ void createGraphicsShaderStageInfo() globalShaderStageInfo[1] = fragShaderStageInfo; } +void createComputeShaderStageInfo() +{ + VkPipelineShaderStageCreateInfo compShaderStageInfo{}; + compShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + compShaderStageInfo.stage = VK_SHADER_STAGE_COMPUTE_BIT; + compShaderStageInfo.pName = "main"; + compShaderStageInfo.module = loadSPIRVShader(SHADERS_PATH + PATH_SEPARATOR "headless.comp.spv"); + + globalShaderStageInfo[2] = compShaderStageInfo; +} + VkResult createRenderPass() { VkResult result = VK_SUCCESS; @@ -315,8 +338,30 @@ VkResult createGraphicsPipeline() { VkResult result; + // Create descriptor set layout with YCbCr sampler as immutable sampler + VkDescriptorSetLayoutBinding samplerBinding = {}; + samplerBinding.binding = 0; + samplerBinding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + samplerBinding.descriptorCount = 1; + samplerBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + samplerBinding.pImmutableSamplers = &globalYcbcrSampler; // Use YCbCr sampler as immutable sampler + + VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {}; + descriptorSetLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + descriptorSetLayoutCreateInfo.bindingCount = 1; + descriptorSetLayoutCreateInfo.pBindings = &samplerBinding; + + result = vkCreateDescriptorSetLayout(globalDev, &descriptorSetLayoutCreateInfo, nullptr, &globalGraphicsDescriptorSetLayout); + if (result != VK_SUCCESS) { + std::cout << "Failed to create graphics descriptor set layout" << std::endl; + return result; + } + LOG("vkCreateDescriptorSetLayout - Graphics Pipeline"); + VkPipelineLayoutCreateInfo layoutCreateInfo = {}; - layoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + layoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + layoutCreateInfo.setLayoutCount = 1; + layoutCreateInfo.pSetLayouts = &globalGraphicsDescriptorSetLayout; result = vkCreatePipelineLayout(globalDev, &layoutCreateInfo, nullptr, &globalGraphicsPipelineLayout); LOG("vkCreatePipelineLayout - Graphics Pipeline"); @@ -388,45 +433,132 @@ VkResult createComputePipeline() { VkResult result; - VkDescriptorSetLayoutBinding binding = {}; - binding.binding = 0; - binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - binding.descriptorCount = 1; - binding.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; + // Create bindings: one for uniform buffer, one for YCbCr sampler as immutable sampler + VkDescriptorSetLayoutBinding bindings[2] = {}; + + // Uniform buffer binding + bindings[0].binding = 0; + bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + bindings[0].descriptorCount = 1; + bindings[0].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; + + // YCbCr sampler binding as immutable sampler + bindings[1].binding = 1; + bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + bindings[1].descriptorCount = 1; + bindings[1].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; + bindings[1].pImmutableSamplers = &globalYcbcrSampler; // Use YCbCr sampler as immutable sampler VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {}; descriptorSetLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - descriptorSetLayoutCreateInfo.bindingCount = 1; - descriptorSetLayoutCreateInfo.pBindings = &binding; + descriptorSetLayoutCreateInfo.bindingCount = 2; + descriptorSetLayoutCreateInfo.pBindings = bindings; vkCreateDescriptorSetLayout(globalDev, &descriptorSetLayoutCreateInfo, nullptr, &globalDescriptorSetLayout); - + VkPipelineLayoutCreateInfo layoutCreateInfo = {}; layoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; layoutCreateInfo.setLayoutCount = 1; layoutCreateInfo.pSetLayouts = &globalDescriptorSetLayout; - result = vkCreatePipelineLayout(globalDev, &layoutCreateInfo, nullptr, &globalComputePipelineLayout); LOG("vkCreatePipelineLayout - Compute Pipeline"); - VkComputePipelineCreateInfo computePipelineCreateInfo = {}; - computePipelineCreateInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; - computePipelineCreateInfo.layout = globalComputePipelineLayout; + VkComputePipelineCreateInfo pipelineCreateInfo = {}; + pipelineCreateInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; + pipelineCreateInfo.layout = globalComputePipelineLayout; + pipelineCreateInfo.stage = globalShaderStageInfo[2]; - VkPipelineShaderStageCreateInfo shaderStage = {}; - shaderStage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - shaderStage.stage = VK_SHADER_STAGE_COMPUTE_BIT; - shaderStage.module = loadSPIRVShader(SHADERS_PATH + PATH_SEPARATOR "headless.comp.spv"); - shaderStage.pName = "main"; + result = vkCreateComputePipelines(globalDev, VK_NULL_HANDLE, 1, &pipelineCreateInfo, nullptr, &globalComputePipeline); + LOG("vkCreateComputePipelines"); - globalShaderStageInfo[2] = shaderStage; + return result; +} - computePipelineCreateInfo.stage = shaderStage; +VkResult createYcbcrSamplers() +{ + VkResult result; - result = vkCreateComputePipelines(globalDev, VK_NULL_HANDLE, 1, &computePipelineCreateInfo, NULL, &globalComputePipeline); - LOG("vkCreateComputePipelines"); + // Check if YCbCr conversion feature is supported + VkPhysicalDeviceFeatures2 features2 = {}; + features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; - return result; + VkPhysicalDeviceSamplerYcbcrConversionFeatures ycbcrFeatures = {}; + ycbcrFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES; + features2.pNext = &ycbcrFeatures; + + vkGetPhysicalDeviceFeatures2(globalPhysdevs[0], &features2); + + if (!ycbcrFeatures.samplerYcbcrConversion) { + std::cout << "YCbCr conversion not supported, skipping YCbCr sampler test" << std::endl; + return VK_SUCCESS; + } + + // Create YCbCr conversion + VkSamplerYcbcrConversionCreateInfo ycbcrCreateInfo = {}; + ycbcrCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO; + ycbcrCreateInfo.format = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM; + ycbcrCreateInfo.ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709; + ycbcrCreateInfo.ycbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL; + ycbcrCreateInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + ycbcrCreateInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + ycbcrCreateInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + ycbcrCreateInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + ycbcrCreateInfo.xChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN; + ycbcrCreateInfo.yChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN; + ycbcrCreateInfo.chromaFilter = VK_FILTER_NEAREST; + ycbcrCreateInfo.forceExplicitReconstruction = VK_FALSE; + + result = vkCreateSamplerYcbcrConversion(globalDev, &ycbcrCreateInfo, nullptr, &globalYcbcrConversion); + if (result != VK_SUCCESS) { + std::cout << "Failed to create YCbCr conversion" << std::endl; + return result; + } + LOG("vkCreateSamplerYcbcrConversion"); + + // Create sampler with YCbCr conversion + VkSamplerYcbcrConversionInfo ycbcrInfo = {}; + ycbcrInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO; + ycbcrInfo.conversion = globalYcbcrConversion; + + VkSamplerCreateInfo samplerCreateInfo = {}; + samplerCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + samplerCreateInfo.pNext = &ycbcrInfo; + samplerCreateInfo.magFilter = VK_FILTER_LINEAR; + samplerCreateInfo.minFilter = VK_FILTER_LINEAR; + samplerCreateInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR; + samplerCreateInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerCreateInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerCreateInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; + samplerCreateInfo.anisotropyEnable = VK_FALSE; + samplerCreateInfo.unnormalizedCoordinates = VK_FALSE; + + result = vkCreateSampler(globalDev, &samplerCreateInfo, nullptr, &globalYcbcrSampler); + if (result != VK_SUCCESS) { + std::cout << "Failed to create YCbCr sampler" << std::endl; + vkDestroySamplerYcbcrConversion(globalDev, globalYcbcrConversion, nullptr); + globalYcbcrConversion = VK_NULL_HANDLE; + return result; + } + LOG("vkCreateSampler with YCbCr conversion"); + + // YCbCr sampler and conversion will be cleaned up in destroyYcbcrSamplers() + + return VK_SUCCESS; +} + +void destroyYcbcrSamplers() +{ + if (globalYcbcrSampler != VK_NULL_HANDLE) { + vkDestroySampler(globalDev, globalYcbcrSampler, nullptr); + globalYcbcrSampler = VK_NULL_HANDLE; + std::cout << "Destroyed YCbCr sampler OK" << std::endl; + } + + if (globalYcbcrConversion != VK_NULL_HANDLE) { + vkDestroySamplerYcbcrConversion(globalDev, globalYcbcrConversion, nullptr); + globalYcbcrConversion = VK_NULL_HANDLE; + std::cout << "Destroyed YCbCr conversion OK" << std::endl; + } } bool compareUUID(uint8_t* uuidGraphics, uint8_t* uuidCompute) @@ -494,12 +626,14 @@ bool checkPipelinePropertiesEXT() static VkResult cleanup() { + destroyYcbcrSamplers(); vkDestroyRenderPass(globalDev, globalRenderPass, nullptr); vkDestroyPipeline(globalDev, globalGraphicsPipeline, nullptr); vkDestroyPipeline(globalDev, globalComputePipeline, nullptr); vkDestroyPipelineLayout(globalDev, globalGraphicsPipelineLayout, nullptr); vkDestroyPipelineLayout(globalDev, globalComputePipelineLayout, nullptr); vkDestroyDescriptorSetLayout(globalDev, globalDescriptorSetLayout, nullptr); + vkDestroyDescriptorSetLayout(globalDev, globalGraphicsDescriptorSetLayout, nullptr); vkDestroyShaderModule(globalDev, globalShaderStageInfo[0].module, nullptr); vkDestroyShaderModule(globalDev, globalShaderStageInfo[1].module, nullptr); vkDestroyShaderModule(globalDev, globalShaderStageInfo[2].module, nullptr); @@ -536,7 +670,7 @@ static bool parseCommandLineArgs(int argc, char** argv) } else { // There was no argument to the destination option. std::cerr << "--shaders option requires one argument." << std::endl; return false; - } + } } else { show_usage(argv[0]); return false; @@ -571,9 +705,12 @@ int main(int argc, char** argv) CHECK_RESULT(createLogicalDevice()); createGraphicsShaderStageInfo(); + createComputeShaderStageInfo(); CHECK_RESULT(createRenderPass()); + CHECK_RESULT(createYcbcrSamplers()); + CHECK_RESULT(createGraphicsPipeline()); CHECK_RESULT(createComputePipeline()); diff --git a/layersvt/vulkan_json_data.hpp b/layersvt/vulkan_json_data.hpp index f67b975eef..8a9e2669a8 100644 --- a/layersvt/vulkan_json_data.hpp +++ b/layersvt/vulkan_json_data.hpp @@ -68,6 +68,9 @@ static void dumpPNextChain(const void* pNext); #define INDENT(sz) s_num_spaces += (sz); +// Forward declaration for layer-provided accessor used by serializer +int GetYcbcrConversionIdForPrint(VkSamplerYcbcrConversion conversion); + #define PRINT_VAL(c) PRINT_SPACE \ if (s != "") {\ _OUT << "\"" << s << "\"" << " : " << o << (c ? "," : "") << std::endl; \ @@ -14525,18 +14528,45 @@ static void print_VkRenderPassBeginInfo(const VkRenderPassBeginInfo * obj, const static void print_VkSamplerYcbcrConversion(VkSamplerYcbcrConversion obj, const std::string& str, bool commaNeeded=true) { PRINT_SPACE - if (commaNeeded) - _OUT << "\"" << str << "\"" << "," << std::endl; - else - _OUT << "\"" << str << "\"" << std::endl; -} + if (str != "") _OUT << "\"" << str << "\"" << " : "; + // Use layer accessor to translate handle to integer ID for JSON + int conversionId = ::vk_json::GetYcbcrConversionIdForPrint(obj); + if (conversionId >= 0) { + if (commaNeeded) + _OUT << conversionId << "," << std::endl; + else + _OUT << conversionId << std::endl; + } else { + if (commaNeeded) + _OUT << "\"\"" << "," << std::endl; + else + _OUT << "\"\"" << std::endl; + } + } static void print_VkSamplerYcbcrConversion(const VkSamplerYcbcrConversion * obj, const std::string& str, bool commaNeeded=true) { PRINT_SPACE - if (commaNeeded) - _OUT << "\"" << str << "\"" << "," << std::endl; - else - _OUT << "\"" << str << "\"" << std::endl; -} + if (str != "") _OUT << "\"" << str << "\"" << " : "; + if (obj) { + // Use layer accessor to translate handle to integer ID for JSON + int conversionId = ::vk_json::GetYcbcrConversionIdForPrint(*obj); + if (conversionId >= 0) { + if (commaNeeded) + _OUT << conversionId << "," << std::endl; + else + _OUT << conversionId << std::endl; + } else { + if (commaNeeded) + _OUT << "\"\"" << "," << std::endl; + else + _OUT << "\"\"" << std::endl; + } + } else { + if (commaNeeded) + _OUT << "\"\"" << "," << std::endl; + else + _OUT << "\"\"" << std::endl; + } + } static void print_VkDescriptorUpdateTemplate(VkDescriptorUpdateTemplate obj, const std::string& str, bool commaNeeded=true) { PRINT_SPACE @@ -18179,17 +18209,17 @@ static void print_VkSamplerYcbcrConversionInfo(VkSamplerYcbcrConversionInfo obj, _OUT << "\"pNext\":" << "\"NULL\""<< ","<< std::endl; } - /** Note: printing just an empty entry here **/ - PRINT_SPACE _OUT << "\"" << "conversion" << "\"" << " : " << "\"" << "\"" << std::endl; + // Print mapped conversion ID + print_VkSamplerYcbcrConversion(obj.conversion, "conversion", 0); - INDENT(-4); - PRINT_SPACE - if (commaNeeded) - _OUT << "}," << std::endl; - else - _OUT << "}" << std::endl; -} -static void print_VkSamplerYcbcrConversionInfo(const VkSamplerYcbcrConversionInfo * obj, const std::string& s, bool commaNeeded=true) { + INDENT(-4); + PRINT_SPACE + if (commaNeeded) + _OUT << "}," << std::endl; + else + _OUT << "}" << std::endl; + } + static void print_VkSamplerYcbcrConversionInfo(const VkSamplerYcbcrConversionInfo * obj, const std::string& s, bool commaNeeded=true) { PRINT_SPACE _OUT << "{" << std::endl; INDENT(4); @@ -18203,13 +18233,13 @@ static void print_VkSamplerYcbcrConversionInfo(const VkSamplerYcbcrConversionInf _OUT << "\"pNext\":" << "\"NULL\""<< ","<< std::endl; } - /** Note: printing just an empty entry here **/ - PRINT_SPACE _OUT << "\"" << "conversion" << "\"" << " : " << "\"" << "\"" << std::endl; + // Print mapped conversion ID + print_VkSamplerYcbcrConversion(obj->conversion, "conversion", 0); - INDENT(-4); - PRINT_SPACE - if (commaNeeded) - _OUT << "}," << std::endl; + INDENT(-4); + PRINT_SPACE + if (commaNeeded) + _OUT << "}," << std::endl; else _OUT << "}" << std::endl; } @@ -24091,6 +24121,8 @@ static void dumpPNextChain(const void* pNext) { break; case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES:print_VkPhysicalDeviceVulkan12Properties((VkPhysicalDeviceVulkan12Properties *) pNext, "VkPhysicalDeviceVulkan12Properties", true); break; + case VK_STRUCTURE_TYPE_APPLICATION_INFO: + break; default: assert(false); // No structure type matching } } @@ -24098,4 +24130,4 @@ static void dumpPNextChain(const void* pNext) { }//End of namespace vk_json -#endif // _VULKAN_JSON_DATA_HPP \ No newline at end of file +#endif // _VULKAN_JSON_DATA_HPP diff --git a/layersvt/vulkan_json_layer.hpp b/layersvt/vulkan_json_layer.hpp index f760468026..db9aaca3d1 100644 --- a/layersvt/vulkan_json_layer.hpp +++ b/layersvt/vulkan_json_layer.hpp @@ -19,6 +19,15 @@ #pragma once #include +#include +#include +#include +#include +#include +#include +#include +#include +#include #ifdef __linux__ #include #endif // __linux__ @@ -38,7 +47,7 @@ #define EXPORT_FUNCTION #endif -namespace vk_json +namespace vk_json { struct ObjectResCreateInfo { @@ -195,7 +204,7 @@ class PipelineData { std::stringstream ss; ss << i << "_" << j; std::string s(ss.str()); - VkSampler sampler = (const_cast(b.pImmutableSamplers[i])); + VkSampler sampler = (const_cast(b.pImmutableSamplers[j])); m_ImmutableSamplerBindingMap.insert(std::make_pair(sampler, s)); } } @@ -208,7 +217,7 @@ class PipelineData { m_renderPass2Flag = true; m_renderPassFlag = false; clearString(); - + INDENT(INDENT_RENDERPASS); { print_VkRenderPassCreateInfo2(pCreateInfo, "RenderPass2"); @@ -228,7 +237,7 @@ class PipelineData { m_renderPassFlag = true; m_renderPass2Flag = false; clearString(); - + INDENT(INDENT_RENDERPASS); { print_VkRenderPassCreateInfo(pCreateInfo, "RenderPass"); @@ -243,7 +252,7 @@ class PipelineData { INDENT(-INDENT_RENDERPASS); } - void setPhysicalDeviceFeatures2(const VkPhysicalDeviceFeatures2* pFeatures) + void setPhysicalDeviceFeatures2(const VkPhysicalDeviceFeatures2* pFeatures) { clearString(); @@ -276,7 +285,7 @@ class PipelineData { assert(result == VK_SUCCESS); } - void setShaderModuleInfo(const VkShaderModuleCreateInfo* pCreateInfo, VkShaderModule* m) + void setShaderModuleInfo(const VkShaderModuleCreateInfo* pCreateInfo, VkShaderModule* m) { if (pCreateInfo == nullptr || m == nullptr) { std::cout << "Error with shader module!" << std::endl; @@ -297,7 +306,65 @@ class PipelineData { std::cout << "Error with sampler!" << std::endl; exit(-1); } - m_samplerInfoMap.insert(std::make_pair(*pSampler, *pCreateInfo)); + + // Create a copy of the sampler create info and explicitly ensure sType is correct + VkSamplerCreateInfo samplerInfo = {}; + samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; + samplerInfo.pNext = pCreateInfo->pNext; + samplerInfo.flags = pCreateInfo->flags; + samplerInfo.magFilter = pCreateInfo->magFilter; + samplerInfo.minFilter = pCreateInfo->minFilter; + samplerInfo.mipmapMode = pCreateInfo->mipmapMode; + samplerInfo.addressModeU = pCreateInfo->addressModeU; + samplerInfo.addressModeV = pCreateInfo->addressModeV; + samplerInfo.addressModeW = pCreateInfo->addressModeW; + samplerInfo.mipLodBias = pCreateInfo->mipLodBias; + samplerInfo.anisotropyEnable = pCreateInfo->anisotropyEnable; + samplerInfo.maxAnisotropy = pCreateInfo->maxAnisotropy; + samplerInfo.compareEnable = pCreateInfo->compareEnable; + samplerInfo.compareOp = pCreateInfo->compareOp; + samplerInfo.minLod = pCreateInfo->minLod; + samplerInfo.maxLod = pCreateInfo->maxLod; + samplerInfo.borderColor = pCreateInfo->borderColor; + samplerInfo.unnormalizedCoordinates = pCreateInfo->unnormalizedCoordinates; + + // Check for YCbCr conversion info in pNext chain and store it persistently + const VkBaseInStructure* pNext = reinterpret_cast(pCreateInfo->pNext); + while (pNext != nullptr) { + if (pNext->sType == VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO) { + const VkSamplerYcbcrConversionInfo* ycbcrInfo = reinterpret_cast(pNext); + // Store a copy of the YCbCr conversion info + m_samplerYcbcrInfoMap.insert(std::make_pair(*pSampler, *ycbcrInfo)); + // Update the sampler create info to point to our persistent copy + samplerInfo.pNext = &m_samplerYcbcrInfoMap[*pSampler]; + // Also store the association + setYcbcrSamplerConversionAssociation(*pSampler, ycbcrInfo->conversion); + break; + } + pNext = pNext->pNext; + } + + // Store the modified sampler create info with persistent pNext chain + m_samplerInfoMap.insert(std::make_pair(*pSampler, samplerInfo)); + } + + void setYcbcrConversionInfo(const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, VkSamplerYcbcrConversion* pYcbcrConversion) + { + if (pCreateInfo == nullptr || pYcbcrConversion == nullptr) { + std::cout << "Error with YCbCr conversion!" << std::endl; + exit(-1); + } + m_ycbcrConversionInfoMap.insert(std::make_pair(*pYcbcrConversion, *pCreateInfo)); + } + + void setYcbcrSamplerConversionAssociation(VkSampler sampler, VkSamplerYcbcrConversion conversion) + { + m_ycbcrSamplerConversionMap.insert(std::make_pair(sampler, conversion)); + } + + void deleteYcbcrConversionInfo(VkSamplerYcbcrConversion ycbcrConversion) + { + m_ycbcrConversionInfoMap.erase(ycbcrConversion); } void setDevice(const VkDeviceCreateInfo* pCreateInfo) @@ -416,13 +483,8 @@ class PipelineData { vk_json::_string_stream << "{" << std::endl; vk_json::s_num_spaces += 4; - // TODO: This is not supported right now, so leaving this empty. - for (int i = 0; i < vk_json::s_num_spaces; i++) vk_json::_string_stream << " "; - vk_json::_string_stream << "\"YcbcrSamplers\" :" << std::endl; - for (int i = 0; i < vk_json::s_num_spaces; i++) vk_json::_string_stream << " "; - vk_json::_string_stream << "[" << std::endl; - for (int i = 0; i < vk_json::s_num_spaces; i++) vk_json::_string_stream << " "; - vk_json::_string_stream << "]," << std::endl; + // Gather and dump YCbCr Samplers. + dumpYcbcrSamplers(); // Gather and dump Immutable Samplers. dumpImmutableSamplers(); @@ -437,7 +499,7 @@ class PipelineData { if (pipelineLayoutCreateInfoString && !pipelineLayoutCreateInfoString->empty()) { for (int i = 0; i < vk_json::s_num_spaces; i++) vk_json::_string_stream << " "; - vk_json::_string_stream << "\"PipelineLayout\" : " << std::endl; + vk_json::_string_stream << "\"PipelineLayout\" :" << std::endl; vk_json::_string_stream << *pipelineLayoutCreateInfoString; } else { std::cout << "Error: No pipeline layout information available. Exiting!\n"; @@ -447,7 +509,7 @@ class PipelineData { // Dump ComputePipeline if (!computePipelineCreateInfoString.empty()) { for (int i = 0; i < vk_json::s_num_spaces; i++) vk_json::_string_stream << " "; - vk_json::_string_stream << "\"ComputePipeline\" : " << std::endl; + vk_json::_string_stream << "\"ComputePipeline\" :" << std::endl; vk_json::_string_stream << computePipelineCreateInfoString; } else { std::cout << "Error: No compute pipeline information available. Exiting!\n"; @@ -486,7 +548,7 @@ class PipelineData { // device extensions { for (int i = 0; i < vk_json::s_num_spaces; i++) vk_json::_string_stream << " "; - vk_json::_string_stream << "\"EnabledExtensions\" : " << std::endl; + vk_json::_string_stream << "\"EnabledExtensions\" :" << std::endl; for (int i = 0; i < vk_json::s_num_spaces; i++) vk_json::_string_stream << " "; vk_json::_string_stream << "[" << std::endl; vk_json::s_num_spaces += 4; @@ -506,7 +568,7 @@ class PipelineData { // Dump Pipeline Identifier for (int i = 0; i < vk_json::s_num_spaces; i++) vk_json::_string_stream << " "; - vk_json::_string_stream << "\"PipelineUUID\" : " << std::endl; + vk_json::_string_stream << "\"PipelineUUID\" :" << std::endl; for (int i = 0; i < vk_json::s_num_spaces; i++) vk_json::_string_stream << " "; vk_json::_string_stream << "[" << std::endl; vk_json::s_num_spaces += 4; @@ -527,7 +589,7 @@ class PipelineData { } } - void dumpImmutableSamplers() + void dumpImmutableSamplers() { for (int i = 0; i < vk_json::s_num_spaces; i++) vk_json::_string_stream << " "; vk_json::_string_stream << "\"ImmutableSamplers\" :" << std::endl; @@ -544,7 +606,7 @@ class PipelineData { vk_json::s_num_spaces += 4; for (int i = 0; i < vk_json::s_num_spaces; i++) vk_json::_string_stream << " "; - vk_json::_string_stream << "\"" << "\"pImmutableSamplers_" << m_ImmutableSamplerBindingMap[keyVal.first] << "\" : " << std::endl; + vk_json::_string_stream << "\"pImmutableSamplers_" << m_ImmutableSamplerBindingMap[keyVal.first] << "\" :" << std::endl; VkSamplerCreateInfo s = m_samplerInfoMap[keyVal.first]; print_VkSamplerCreateInfo(s, "ImmutableSamplers", (count + 1 != sz)); @@ -564,6 +626,70 @@ class PipelineData { vk_json::_string_stream << "]," << std::endl; } + void dumpYcbcrSamplers() + { + for (int i = 0; i < vk_json::s_num_spaces; i++) vk_json::_string_stream << " "; + vk_json::_string_stream << "\"YcbcrSamplers\" :" << std::endl; + for (int i = 0; i < vk_json::s_num_spaces; i++) vk_json::_string_stream << " "; + vk_json::_string_stream << "[" << std::endl; + vk_json::s_num_spaces += 4; + + // Collect unique YCbCr conversions used by immutable samplers in this pipeline + std::map conversionToIdMap; + int nextId = 1000; // Start with a base ID to avoid conflicts + + for (const auto& immutableSamplerPair : m_ImmutableSamplerBindingMap) { + VkSampler sampler = immutableSamplerPair.first; + // Check if this immutable sampler has a YCbCr conversion + if (m_ycbcrSamplerConversionMap.find(sampler) != m_ycbcrSamplerConversionMap.end()) { + VkSamplerYcbcrConversion conversion = m_ycbcrSamplerConversionMap[sampler]; + if (conversionToIdMap.find(conversion) == conversionToIdMap.end()) { + conversionToIdMap[conversion] = nextId++; + } + } + } + + int sz = (int)conversionToIdMap.size(); + int count = 0; + + // Output YCbCr conversions with integer IDs + for (const auto& conversionIdPair : conversionToIdMap) { + VkSamplerYcbcrConversion conversion = conversionIdPair.first; + int conversionId = conversionIdPair.second; + + for (int i = 0; i < vk_json::s_num_spaces; i++) vk_json::_string_stream << " "; + vk_json::_string_stream << "{" << std::endl; + vk_json::s_num_spaces += 4; + + // Output conversion with integer ID as key + for (int i = 0; i < vk_json::s_num_spaces; i++) vk_json::_string_stream << " "; + vk_json::_string_stream << "\"" << conversionId << "\" :" << std::endl; + + if (m_ycbcrConversionInfoMap.find(conversion) != m_ycbcrConversionInfoMap.end()) { + VkSamplerYcbcrConversionCreateInfo conversionInfo = m_ycbcrConversionInfoMap[conversion]; + print_VkSamplerYcbcrConversionCreateInfo(conversionInfo, "YcbcrConversion", (count + 1 != sz)); + } + + vk_json::s_num_spaces -= 4; + for (int i = 0; i < vk_json::s_num_spaces; i++) vk_json::_string_stream << " "; + + if (count + 1 != sz) + vk_json::_string_stream << "}," << std::endl; + else + vk_json::_string_stream << "}" << std::endl; + + count++; + } + + // Store the mapping for use by ImmutableSamplers section + m_conversionToIdMap = conversionToIdMap; + + + vk_json::s_num_spaces -= 4; + for (int i = 0; i < vk_json::s_num_spaces; i++) vk_json::_string_stream << " "; + vk_json::_string_stream << "]," << std::endl; + } + void dumpDescriptorSets(VkDevice &device, VkPipelineLayout layout, std::vector &pLayoutsHashStringList) { int count = 0; @@ -606,7 +732,7 @@ class PipelineData { vk_json::_string_stream << "]," << std::endl; } - std::stringstream dumpShaders(uint32_t stageCount, const VkPipelineShaderStageCreateInfo* pStages) + std::stringstream dumpShaders(uint32_t stageCount, const VkPipelineShaderStageCreateInfo* pStages) { std::string jsonShaderString = ""; std::stringstream shaderCode; @@ -721,24 +847,19 @@ class PipelineData { if (renderPassCreateInfoString && !renderPassCreateInfoString->empty()) { for (int i = 0; i < vk_json::s_num_spaces; i++) vk_json::_string_stream << " "; if (m_renderPassFlag) { - vk_json::_string_stream << "\"Renderpass\" : " << std::endl; + vk_json::_string_stream << "\"Renderpass\" :" << std::endl; } else if (m_renderPass2Flag) { - vk_json::_string_stream << "\"Renderpass2\" : " << std::endl; + vk_json::_string_stream << "\"Renderpass2\" :" << std::endl; } vk_json::_string_stream << *renderPassCreateInfoString << std::endl; } else { std::cout << "Error: No renderpass information available. Exiting!\n"; exit(-1); } - - // TODO: This is not supported right now, so leaving this empty. - for (int i = 0; i < vk_json::s_num_spaces; i++) vk_json::_string_stream << " "; - vk_json::_string_stream << "\"YcbcrSamplers\" :" << std::endl; - for (int i = 0; i < vk_json::s_num_spaces; i++) vk_json::_string_stream << " "; - vk_json::_string_stream << "[" << std::endl; - for (int i = 0; i < vk_json::s_num_spaces; i++) vk_json::_string_stream << " "; - vk_json::_string_stream << "]," << std::endl; + + // Gather and dump YCbCr Samplers. + dumpYcbcrSamplers(); // Gather and dump Immutable Samplers. dumpImmutableSamplers(); @@ -752,7 +873,7 @@ class PipelineData { std::string *pipelineLayoutCreateInfoString = getPrivateData(device, VK_OBJECT_TYPE_PIPELINE_LAYOUT, reinterpret_cast(pCreateInfos[cnt].layout)); if (pipelineLayoutCreateInfoString && !pipelineLayoutCreateInfoString->empty()) { for (int i = 0; i < vk_json::s_num_spaces; i++) vk_json::_string_stream << " "; - vk_json::_string_stream << "\"PipelineLayout\" : " << std::endl; + vk_json::_string_stream << "\"PipelineLayout\" :" << std::endl; vk_json::_string_stream << *pipelineLayoutCreateInfoString; } else { std::cout << "Error: No pipeline layout information available. Exiting!\n"; @@ -762,7 +883,7 @@ class PipelineData { // Dump GraphicsPipeline if (!graphicsPipelineCreateInfoString.empty()) { for (int i = 0; i < vk_json::s_num_spaces; i++) vk_json::_string_stream << " "; - vk_json::_string_stream << "\"GraphicsPipeline\" : " << std::endl; + vk_json::_string_stream << "\"GraphicsPipeline\" :" << std::endl; vk_json::_string_stream << graphicsPipelineCreateInfoString; } else { std::cout << "Error: No graphics pipeline information available. Exiting!\n"; @@ -798,7 +919,7 @@ class PipelineData { // device extensions { for (int i = 0; i < vk_json::s_num_spaces; i++) vk_json::_string_stream << " "; - vk_json::_string_stream << "\"EnabledExtensions\" : " << std::endl; + vk_json::_string_stream << "\"EnabledExtensions\" :" << std::endl; for (int i = 0; i < vk_json::s_num_spaces; i++) vk_json::_string_stream << " "; vk_json::_string_stream << "[" << std::endl; vk_json::s_num_spaces += 4; @@ -818,7 +939,7 @@ class PipelineData { // Dump Pipeline Identifier for (int i = 0; i < vk_json::s_num_spaces; i++) vk_json::_string_stream << " "; - vk_json::_string_stream << "\"PipelineUUID\" : " << std::endl; + vk_json::_string_stream << "\"PipelineUUID\" :" << std::endl; for (int i = 0; i < vk_json::s_num_spaces; i++) vk_json::_string_stream << " "; vk_json::_string_stream << "[" << std::endl; vk_json::s_num_spaces += 4; @@ -883,7 +1004,7 @@ class PipelineData { ss << "\tg_objectResCreateInfo.subpassDescriptionRequestCount = " << 0 << "; // TODO: To be filled\n"; ss << "\tg_objectResCreateInfo.descriptorSetLayoutBindingRequestCount = " << objResInfo.descriptorSetLayoutBindingRequestCount << ";\n"; ss << "\tg_objectResCreateInfo.attachmentDescriptionRequestCount = " << 0 << "; // TODO: To be filled\n"; - ss << "\tg_objectResCreateInfo.samplerYcbcrConversionRequestCount = " << 0 << "; // TODO: To be filled\n"; + ss << "\tg_objectResCreateInfo.samplerYcbcrConversionRequestCount = " << objResInfo.samplerYcbcrConversionRequestCount << ";\n"; ss << "\tg_objectResCreateInfo.descriptorSetLayoutBindingLimit = " << 0 << "; // TODO: To be filled\n"; ss << "\tg_objectResCreateInfo.maxImageViewMipLevels = " << objResInfo.maxImageViewMipLevels << ";\n"; ss << "\tg_objectResCreateInfo.maxImageViewArrayLayers = " << 0 << "; // TODO: To be filled\n"; @@ -901,6 +1022,13 @@ class PipelineData { void clearString() { _string_stream.str(std::string("")); } + int getYcbcrConversionId(VkSamplerYcbcrConversion conversion) const + { + auto it = m_conversionToIdMap.find(conversion); + if (it == m_conversionToIdMap.end()) return -1; + return it->second; + } + private: // TODO: Better way to do this? void getProcessName() @@ -1014,6 +1142,10 @@ class PipelineData { std::map m_pipelineLayoutDescSetMap; std::map m_shaderInfoMap; std::map m_samplerInfoMap; + std::map m_ycbcrConversionInfoMap; + std::map m_ycbcrSamplerConversionMap; + std::map m_samplerYcbcrInfoMap; // Store YCbCr info from pNext chains + std::map m_conversionToIdMap; // Mapping from conversion to integer ID for JSON output std::map m_ImmutableSamplerBindingMap; std::vector m_deviceExtensions; int m_pipelineCount; @@ -1028,6 +1160,11 @@ static PipelineData s_pipe; } // namespace vk_json +namespace vk_json { +inline int GetYcbcrConversionIdForPrint(VkSamplerYcbcrConversion conversion) { + return s_pipe.getYcbcrConversionId(conversion); +} +} // mark any features implemented in the layer as supported void set_layer_supported_features(VkPhysicalDeviceFeatures2 *pFeatures) diff --git a/scripts/json_gen_generator.py b/scripts/json_gen_generator.py index 35d0ce4d4a..576b3300b7 100644 --- a/scripts/json_gen_generator.py +++ b/scripts/json_gen_generator.py @@ -77,7 +77,7 @@ initInstanceTable(*pInstance, fpGetInstanceProcAddr); }} {funcStateTrackingCode} - + return result; }} @end function @@ -179,6 +179,47 @@ }} @end function +@foreach function where('{funcName}' == 'vkCreateSamplerYcbcrConversion') +EXPORT_FUNCTION VKAPI_ATTR {funcReturn} VKAPI_CALL {funcName}({funcTypedParams}) +{{ + {funcReturn} result = device_dispatch_table({funcDispatchParam})->{funcShortName}({funcNamedParams}); + {funcStateTrackingCode} + + // Store YCbCr conversion info for JSON layer + if (result == VK_SUCCESS) {{ + vk_json::s_pipe.setYcbcrConversionInfo(pCreateInfo, pYcbcrConversion); + }} + + return result; +}} +@end function + +@foreach function where('{funcName}' == 'vkCreateSampler') +EXPORT_FUNCTION VKAPI_ATTR {funcReturn} VKAPI_CALL {funcName}({funcTypedParams}) +{{ + {funcReturn} result = device_dispatch_table({funcDispatchParam})->{funcShortName}({funcNamedParams}); + {funcStateTrackingCode} + + // Store sampler info and check for YCbCr conversion association + if (result == VK_SUCCESS) {{ + vk_json::s_pipe.setSamplerInfo(pCreateInfo, pSampler); + }} + + return result; +}} +@end function + +@foreach function where('{funcName}' == 'vkDestroySamplerYcbcrConversion') +EXPORT_FUNCTION VKAPI_ATTR {funcReturn} VKAPI_CALL {funcName}({funcTypedParams}) +{{ + // Clean up YCbCr conversion info before destroying + vk_json::s_pipe.deleteYcbcrConversionInfo(ycbcrConversion); + + device_dispatch_table({funcDispatchParam})->{funcShortName}({funcNamedParams}); + {funcStateTrackingCode} +}} +@end function + // Autogen instance functions @foreach function where('{funcDispatchType}' == 'instance' and '{funcReturn}' != 'void' and '{funcName}' not in ['vkCreateInstance', 'vkDestroyInstance', 'vkCreateDevice', 'vkGetInstanceProcAddr', 'vkEnumerateDeviceExtensionProperties', 'vkEnumerateDeviceLayerProperties']) @@ -195,30 +236,30 @@ {{ instance_dispatch_table({funcDispatchParam})->{funcShortName}({funcNamedParams}); {funcStateTrackingCode} - + }} @end function // Autogen device functions -@foreach function where('{funcDispatchType}' == 'device' and '{funcReturn}' != 'void' and '{funcName}' not in ['vkDestroyDevice', 'vkEnumerateInstanceExtensionProperties', 'vkEnumerateInstanceLayerProperties', 'vkQueuePresentKHR', 'vkGetDeviceProcAddr', 'vkGetPipelinePropertiesEXT']) +@foreach function where('{funcDispatchType}' == 'device' and '{funcReturn}' != 'void' and '{funcName}' not in ['vkDestroyDevice', 'vkEnumerateInstanceExtensionProperties', 'vkEnumerateInstanceLayerProperties', 'vkQueuePresentKHR', 'vkGetDeviceProcAddr', 'vkGetPipelinePropertiesEXT', 'vkCreateSampler', 'vkCreateSamplerYcbcrConversion']) EXPORT_FUNCTION VKAPI_ATTR {funcReturn} VKAPI_CALL {funcName}({funcTypedParams}) {{ - + {funcReturn} result = device_dispatch_table({funcDispatchParam})->{funcShortName}({funcNamedParams}); {funcStateTrackingCode} - + return result; }} @end function -@foreach function where('{funcDispatchType}' == 'device' and '{funcReturn}' == 'void' and '{funcName}' not in ['vkDestroyDevice', 'vkEnumerateInstanceExtensionProperties', 'vkEnumerateInstanceLayerProperties', 'vkGetDeviceProcAddr']) +@foreach function where('{funcDispatchType}' == 'device' and '{funcReturn}' == 'void' and '{funcName}' not in ['vkDestroyDevice', 'vkEnumerateInstanceExtensionProperties', 'vkEnumerateInstanceLayerProperties', 'vkGetDeviceProcAddr', 'vkDestroySamplerYcbcrConversion']) EXPORT_FUNCTION VKAPI_ATTR {funcReturn} VKAPI_CALL {funcName}({funcTypedParams}) {{ - + device_dispatch_table({funcDispatchParam})->{funcShortName}({funcNamedParams}); {funcStateTrackingCode} - + }} @end function @@ -272,11 +313,11 @@ , 'vkCreateGraphicsPipelines': 'vk_json::s_pipe.objResInfo.graphicsPipelineRequestCount += createInfoCount;\n' - '\tvk_json::s_pipe.dumpGraphicsPipeline(device, createInfoCount, pCreateInfos, pPipelines);' + '\tvk_json::s_pipe.dumpGraphicsPipeline(device, createInfoCount, pCreateInfos, pPipelines);' , 'vkCreateComputePipelines': 'vk_json::s_pipe.objResInfo.computePipelineRequestCount += createInfoCount;\n' - '\tvk_json::s_pipe.dumpComputePipeline(device, createInfoCount, pCreateInfos, pPipelines);' + '\tvk_json::s_pipe.dumpComputePipeline(device, createInfoCount, pCreateInfos, pPipelines);' , 'vkCreateDescriptorSetLayout': 'vk_json::s_pipe.objResInfo.descriptorSetLayoutRequestCount++;\n' @@ -306,6 +347,13 @@ 'vk_json::s_pipe.objResInfo.samplerRequestCount++;\n' '\tvk_json::s_pipe.setSamplerInfo(pCreateInfo, pSampler);' , + 'vkCreateSamplerYcbcrConversion': + 'vk_json::s_pipe.objResInfo.samplerYcbcrConversionRequestCount++;\n' + '\tvk_json::s_pipe.setYcbcrConversionInfo(pCreateInfo, pYcbcrConversion);' + , + 'vkDestroySamplerYcbcrConversion': + 'vk_json::s_pipe.deleteYcbcrConversionInfo(ycbcrConversion);' + , 'vkCreateDevice': '\t// We have seen what the app has requested in vkCreateInstance, and we have assumed that privateData feature is supported.\n' '\t// Now, let us actually validate if that is supported.\n' @@ -386,7 +434,7 @@ 'if (pCreateInfo) {\n' '\t\tvk_json::s_pipe.objResInfo.fenceRequestCount++;\n' '\t}\n' - , + , 'vkCreateBuffer': 'if (pCreateInfo) {\n' '\t\tvk_json::s_pipe.objResInfo.bufferRequestCount++;\n' @@ -396,7 +444,7 @@ 'if (pCreateInfo) {\n' '\t\tvk_json::s_pipe.objResInfo.bufferViewRequestCount++;\n' '\t}\n' - , + , 'vkCreateImage': 'if (pCreateInfo) {\n' '\t\tvk_json::s_pipe.objResInfo.imageRequestCount++;\n' @@ -425,12 +473,12 @@ 'if (pCreateInfo) {\n' '\t\tvk_json::s_pipe.objResInfo.queryPoolRequestCount++;\n' '\t}\n' - , + , 'vkCreateDescriptorPool': 'if (pCreateInfo) {\n' '\t\tvk_json::s_pipe.objResInfo.descriptorPoolRequestCount++;\n' '\t}\n' - , + , 'vkAllocateDescriptorSets': 'if (pAllocateInfo) {\n' '\t\tvk_json::s_pipe.objResInfo.descriptorSetRequestCount += pAllocateInfo->descriptorSetCount;\n' @@ -446,8 +494,8 @@ '\t\tvk_json::s_pipe.objResInfo.commandPoolRequestCount++;\n' '\t}\n' , - - + + } class JSONGenGeneratorOptions(GeneratorOptions): @@ -970,8 +1018,8 @@ def __init__(self, name, value, bitpos, comment): self.name = name self.comment = comment self.multiValue = None - - if value is not None: + + if value is not None: self.multiValue = not isPow2(StrToInt(value)) @@ -1017,7 +1065,7 @@ def __init__(self, rootNode, extensions): childValue = extBase + (extNum - 1) * extBlockSize + extOffset if ('dir' in child.keys()): childValue = -childValue - + # Check for duplicates duplicate = False for o in self.options: @@ -1165,7 +1213,7 @@ def __init__(self, rootNode, constants, aliases, extensions): else: self.dispatchType = 'device' - if self.name in extensions and extensions[self.name].type == 'instance': + if self.name in extensions and extensions[self.name].type == 'instance': self.type = 'instance' else: self.type = self.dispatchType @@ -1188,7 +1236,7 @@ def values(self): 'funcNamedParams': self.namedParams, 'funcTypedParams': self.typedParams, 'funcDispatchParam': self.parameters[0].name, - 'funcDispatchType' : self.dispatchType, + 'funcDispatchType' : self.dispatchType, 'funcStateTrackingCode': self.stateTrackingCode, 'funcSafeToPrint': self.safeToPrint, } @@ -1255,7 +1303,7 @@ def __init__(self, rootNode, constants, enums): self.conditionVars = '' self.structureIndex = -1 - + if(self.structExtends is not None): for member in self.members: if(member.structValues is not None): @@ -1264,7 +1312,7 @@ def __init__(self, rootNode, constants, enums): for opt in enum.options: if(member.structValues == opt.name): self.structureIndex = opt.value - + def values(self): return { 'sctName': self.name,