Skip to content

Commit

Permalink
tests: Debug Printf with uncached buffer
Browse files Browse the repository at this point in the history
  • Loading branch information
dorian-apanel-intel committed Jul 17, 2023
1 parent e770fc2 commit 99bb797
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 4 deletions.
4 changes: 2 additions & 2 deletions layers/gpu_validation/debug_printf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,7 @@ void DebugPrintf::AnalyzeAndGenerateMessages(VkCommandBuffer command_buffer, VkQ
if (!expect && !use_uncached_buffer) return;

uint32_t index = spvtools::kDebugOutputDataOffset;
while (debug_output_buffer[index] && (index < output_buffer_size)) {
while ((index < output_buffer_size) && debug_output_buffer[index]) {
std::stringstream shader_message;
VkShaderModule shader_module_handle = VK_NULL_HANDLE;
VkPipeline pipeline_handle = VK_NULL_HANDLE;
Expand Down Expand Up @@ -816,7 +816,7 @@ void DebugPrintf::AllocateDebugPrintfResources(const VkCommandBuffer cmd_buffer,
VmaAllocationCreateInfo alloc_info = {};
alloc_info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
if (use_uncached_buffer) {
alloc_info.requiredFlags |= VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD;
alloc_info.requiredFlags |= VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD | VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD;
}
result = vmaCreateBuffer(vmaAllocator, &buffer_info, &alloc_info, &output_block.buffer, &output_block.allocation, nullptr);
if (result != VK_SUCCESS) {
Expand Down
9 changes: 9 additions & 0 deletions layers/layer_options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ const char *SETTING_CUSTOM_STYPE_LIST = "custom_stype_list";
const char *SETTING_DUPLICATE_MESSAGE_LIMIT = "duplicate_message_limit";
const char *SETTING_FINE_GRAINED_LOCKING = "fine_grained_locking";

const char *SETTING_DEBUG_PRINTF_UNCACHED_BUFFER = "printf_uncached_buffer";

// Set the local disable flag for the appropriate VALIDATION_CHECK_DISABLE enum
void SetValidationDisable(CHECK_DISABLED &disable_data, const ValidationCheckDisables disable_id) {
switch (disable_id) {
Expand Down Expand Up @@ -374,6 +376,11 @@ static std::string GetConfigValue(const char *setting) {
return getLayerOption(key.c_str());
}

static void SetConfigValue(const char *setting, const char* value) {
const std::string key(GetSettingKey(setting));
return setLayerOption(key.c_str(), value);
}

static std::string GetEnvVarValue(const char *setting) {
std::string env_var = setting;
vvl::ToUpper(env_var);
Expand Down Expand Up @@ -439,6 +446,8 @@ void ProcessConfigAndEnvSettings(ConfigAndEnvSettings *settings_data) {
CreateFilterMessageIdList(data, ",", settings_data->message_filter_list);
} else if (name == SETTING_DUPLICATE_MESSAGE_LIMIT) {
*settings_data->duplicate_message_limit = cur_setting.data.value32;
} else if ((name == SETTING_DEBUG_PRINTF_UNCACHED_BUFFER) && cur_setting.data.valueBool) {
SetConfigValue(SETTING_DEBUG_PRINTF_UNCACHED_BUFFER, "true");
} else if (name == SETTING_CUSTOM_STYPE_LIST) {
if (cur_setting.type == VK_LAYER_SETTING_VALUE_TYPE_STRING_ARRAY_EXT) {
std::string data(cur_setting.data.arrayString.pCharArray);
Expand Down
2 changes: 1 addition & 1 deletion tests/framework/layer_validation_tests.h
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ class VkGpuAssistedLayerTest : public VkLayerTest {

class NegativeDebugPrintf : public VkLayerTest {
public:
void InitDebugPrintfFramework();
void InitDebugPrintfFramework(bool use_uncached_buffer = false);

protected:
};
Expand Down
135 changes: 134 additions & 1 deletion tests/negative/debug_printf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,25 @@

#include "../framework/layer_validation_tests.h"

void NegativeDebugPrintf::InitDebugPrintfFramework() {
class UncachedBufferSetting {
public:
UncachedBufferSetting(const bool use_uncached_buffer /*= false*/) {
setting_value_data.valueBool = use_uncached_buffer;

strncpy(setting_val.name, "printf_uncached_buffer", sizeof(setting_val.name));
setting_val.type = VK_LAYER_SETTING_VALUE_TYPE_BOOL_EXT;
setting_val.data = setting_value_data;
setting = {VK_STRUCTURE_TYPE_INSTANCE_LAYER_SETTINGS_EXT, nullptr, 1, &setting_val};
}
VkLayerSettingsEXT *pnext{&setting};

private:
VkLayerSettingValueDataEXT setting_value_data{};
VkLayerSettingValueEXT setting_val;
VkLayerSettingsEXT setting;
};

void NegativeDebugPrintf::InitDebugPrintfFramework(bool use_uncached_buffer) {
VkValidationFeatureEnableEXT enables[] = {VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT};
VkValidationFeatureDisableEXT disables[] = {
VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT, VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT,
Expand All @@ -24,6 +42,11 @@ void NegativeDebugPrintf::InitDebugPrintfFramework() {
features.pEnabledValidationFeatures = enables;
features.pDisabledValidationFeatures = disables;

auto uncached_buffer_setting = UncachedBufferSetting(use_uncached_buffer);
if (use_uncached_buffer) {
features.pNext = uncached_buffer_setting.pnext;
}

InitFramework(m_errorMonitor, &features);
}

Expand Down Expand Up @@ -1063,3 +1086,113 @@ TEST_F(NegativeDebugPrintf, GPLFragmentIndependentSets) {
vk::QueueWaitIdle(m_device->m_queue);
m_errorMonitor->VerifyFound();
}

TEST_F(NegativeDebugPrintf, UncachedBuffer) {
TEST_DESCRIPTION("Verify that calls to debugPrintfEXT are received in debug stream");
SetTargetApiVersion(VK_API_VERSION_1_1);
AddRequiredExtensions(VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME);
AddRequiredExtensions(VK_AMD_DEVICE_COHERENT_MEMORY_EXTENSION_NAME); // It must be supported but if not enabled
// Debug Printf can force enable it.
InitDebugPrintfFramework(true /*use_uncached_buffer*/);

if (!AreRequiredExtensionsEnabled()) {
GTEST_SKIP() << RequiredExtensionsNotSupported() << " not supported";
}

// deviceCoherentMemory feature needs to be supported, but if not specified or enabled, Debug Printf will force enable it.
auto dcm_features = LvlInitStruct<VkPhysicalDeviceCoherentMemoryFeaturesAMD>();
auto features2 = GetPhysicalDeviceFeatures2(dcm_features);
if (dcm_features.deviceCoherentMemory == 0) {
GTEST_SKIP() << "deviceCoherentMemory feature not supported";
}

ASSERT_NO_FATAL_FAILURE(InitState(nullptr, &dcm_features, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT));
if (DeviceValidationVersion() < VK_API_VERSION_1_1) {
GTEST_SKIP() << "At least Vulkan version 1.1 is required";
}

auto features = m_device->phy().features();
if (!features.vertexPipelineStoresAndAtomics || !features.fragmentStoresAndAtomics) {
GTEST_SKIP() << "GPU-Assisted printf test requires vertexPipelineStoresAndAtomics and fragmentStoresAndAtomics";
}
ASSERT_NO_FATAL_FAILURE(InitViewport());
ASSERT_NO_FATAL_FAILURE(InitRenderTarget());

if (IsPlatform(kMockICD)) {
GTEST_SKIP() << "Test not supported by MockICD, GPU-Assisted validation test requires a driver that can draw";
}
// Make a uniform buffer to be passed to the shader that contains the test number
uint32_t qfi = 0;
VkBufferCreateInfo bci = LvlInitStruct<VkBufferCreateInfo>();
bci.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
bci.size = 8;
bci.queueFamilyIndexCount = 1;
bci.pQueueFamilyIndices = &qfi;

VkPushConstantRange push_constant_range = {VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(float) * 4};

const VkPipelineLayoutObj pipeline_layout(m_device, {}, {push_constant_range});

float push_constants[4] = {0.0, 1.0, 2.0, 3.0};

char const *shader_source = R"glsl(
#version 450
#extension GL_EXT_debug_printf : enable
layout(push_constant, std430) uniform foo { float x[4]; } constants;
void main() {
float myfloat = 3.1415f;
gl_Position = vec4(0.0, 0.0, 0.0, 0.0);
if (gl_VertexIndex == 0) {
debugPrintfEXT("Here are three float values %f, %f, %f", 1.0, myfloat, gl_Position.x);
float x = constants.x[0];
while(x > -1.f) { // infinite loop
x += 0.000001f;
}
debugPrintfEXT("Here is a value that should not be printed %f", x);
}
}
)glsl";
char const *message = "Here are three float values 1.000000, 3.141500, 0.000000";

VkShaderObj vs(this, shader_source, VK_SHADER_STAGE_VERTEX_BIT, SPV_ENV_VULKAN_1_0, SPV_SOURCE_GLSL, nullptr, "main", true);

VkViewport viewport = m_viewports[0];
VkRect2D scissors = m_scissors[0];

VkSubmitInfo submit_info = LvlInitStruct<VkSubmitInfo>();
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &m_commandBuffer->handle();

VkPipelineObj pipe(m_device);
pipe.AddShader(&vs);
pipe.AddDefaultColorAttachment();
pipe.DisableRasterization();
VkResult err = pipe.CreateVKPipeline(pipeline_layout.handle(), renderPass());
ASSERT_VK_SUCCESS(err);

VkCommandBufferBeginInfo begin_info = LvlInitStruct<VkCommandBufferBeginInfo>();
VkCommandBufferInheritanceInfo hinfo = LvlInitStruct<VkCommandBufferInheritanceInfo>();
begin_info.pInheritanceInfo = &hinfo;

m_commandBuffer->begin(&begin_info);
m_commandBuffer->BeginRenderPass(m_renderPassBeginInfo);
vk::CmdBindPipeline(m_commandBuffer->handle(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipe.handle());
vk::CmdPushConstants(m_commandBuffer->handle(), pipeline_layout.handle(), VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(push_constants),
push_constants);
vk::CmdSetViewport(m_commandBuffer->handle(), 0, 1, &viewport);
vk::CmdSetScissor(m_commandBuffer->handle(), 0, 1, &scissors);
vk::CmdDraw(m_commandBuffer->handle(), 3, 1, 0, 0);
vk::CmdEndRenderPass(m_commandBuffer->handle());
m_commandBuffer->end();

m_errorMonitor->SetDesiredFailureMsg(kInformationBit, message);

err = vk::QueueSubmit(m_device->m_queue, 1, &submit_info, VK_NULL_HANDLE);
ASSERT_TRUE((err == VK_SUCCESS) || (err == VK_ERROR_DEVICE_LOST)) << vk_result_string(err);
if (err == VK_SUCCESS) {
err = vk::QueueWaitIdle(m_device->m_queue);
ASSERT_TRUE((err == VK_SUCCESS) || (err == VK_ERROR_DEVICE_LOST)) << vk_result_string(err);
}
m_errorMonitor->VerifyFound();
}

0 comments on commit 99bb797

Please sign in to comment.