I started learning Vulkan and everything went quite well, but somehow, the function vkGetSwapChainImages() wants to ruin my life.
Basically, this is how I create the SwapChain. desiredFormat, desiredExtent, desiredUsage, desiredExtent and desiredTransform are all set well.
VkSwapchainCreateInfoKHR swapChainCreateInfo = { };
swapChainCreateInfo.sType = VkStructureType::VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
swapChainCreateInfo.flags = 0;
swapChainCreateInfo.pNext = nullptr;
swapChainCreateInfo.compositeAlpha = VkCompositeAlphaFlagBitsKHR::VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
swapChainCreateInfo.imageColorSpace = desiredFormat.colorSpace;
swapChainCreateInfo.imageFormat = desiredFormat.format;
swapChainCreateInfo.imageExtent = desiredExtent;
swapChainCreateInfo.clipped = VK_TRUE;
swapChainCreateInfo.imageArrayLayers = 1;
swapChainCreateInfo.imageSharingMode = VkSharingMode::VK_SHARING_MODE_EXCLUSIVE;
swapChainCreateInfo.surface = mRenderingSurface;
swapChainCreateInfo.imageUsage = desiredUsage;
swapChainCreateInfo.minImageCount = desiredImageCount;
swapChainCreateInfo.presentMode = desiredMode;
swapChainCreateInfo.oldSwapchain = oldSwapChain;
swapChainCreateInfo.pQueueFamilyIndices = nullptr;
swapChainCreateInfo.queueFamilyIndexCount = 0;
swapChainCreateInfo.preTransform = desiredTransform;
if ( vkCreateSwapchainKHR( mLogicalDevice, &swapChainCreateInfo, nullptr, &mSwapChain ) != VK_SUCCESS )
return false;
If I call vkGetSwapChainImages nothing bad happens. But if I want to call vkGetSwapChainImages a second time, it doesn't work and I get an exception like this
Exception thrown at 0x0433A209 (VkLayer_core_validation.dll) in Project1.exe: 0xC0000005: Access violation reading location 0x000000A8.
And I don't understand why this happens. I tried saving the results from first call and using them, but I still get an error, so I that there's something I'm doing wrong here.
Related
It seems I have had invalid code for a while but the validation layers were silent. After updating my sdk to the latest version I started getting this error:
Message ID name: VUID-vkQueuePresentKHR-pWaitSemaphores-03268
Message: [ VUID-vkQueuePresentKHR-pWaitSemaphores-03268 ] Object: 0x55b4b87478f0 (Name = Selected logical device : Type = 3) | VkQueue 0x55b4b8224020[Main queue] is waiting on VkSemaphore 0x110000000011[Render Finished Semaphore: 0] that has no way to be signaled. The Vulkan spec states: All elements of the pWaitSemaphores member of pPresentInfo must reference a semaphore signal operation that has been submitted for execution and any semaphore signal operations on which it depends (if any) must have also been submitted for execution. (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-vkQueuePresentKHR-pWaitSemaphores-03268)
Severity: VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT
This happens inside of my main draw loop and it's the only validation layer error in my code. If I never call the code that is responsible for surface presentation. I get no errors.
I am sure the place where I am doing things wrong is here:
void DisplayTarget::StartPass(uint target_num, bool should_clear,
VulkanImage* external_depth)
{
auto device = h_interface->GetDevice();
auto result = device.acquireNextImageKHR(
*swap_chain,
std::numeric_limits<uint64_t>::max(),
*img_available_sems[current_frame],
nullptr,
&active_image_index);
if(result != vk::Result::eSuccess)
Log::RecordLog("Failed to acquire image");
}
vk::Result DisplayTarget::EndPass()
{
auto device = h_interface->GetDevice();
auto cmd_buff = h_interface->GetCmdBuffer();
auto graphics_queue = h_interface->GetQueue();
device.waitForFences(
1,
&*in_flight_fences[current_frame],
VK_TRUE,
std::numeric_limits<uint64_t>::max());
vk::Semaphore wait_semaphores[] = {*img_available_sems[current_frame]};
vk::PipelineStageFlags wait_stages[] = {
vk::PipelineStageFlagBits::eColorAttachmentOutput};
vk::Semaphore signal_semaphores[] = {*render_finished_sems[current_frame]};
vk::SubmitInfo submit_info(
1, wait_semaphores, wait_stages, 1, &cmd_buff, 1, signal_semaphores);
device.resetFences(1, &*in_flight_fences[current_frame]);
auto result =
graphics_queue.submit(1, &submit_info, *in_flight_fences[current_frame]);
if(result != vk::Result::eSuccess)
Log::RecordLog("Failed to submit draw command buffer!");
graphics_queue.waitIdle();
device.waitIdle();
vk::SwapchainKHR swap_chains[] = {*swap_chain};
vk::PresentInfoKHR present_info = {};
present_info.waitSemaphoreCount = 1;
present_info.pWaitSemaphores = signal_semaphores;
present_info.swapchainCount = 1;
present_info.pSwapchains = swap_chains;
present_info.pImageIndices = &active_image_index;
result = graphics_queue.presentKHR(&present_info);
current_frame = (current_frame + 1) % MAX_FRAMES_IN_FLIGHT;
return result;
}
Currently they are called consecutively:
display.StartPass();
display.EndPass();
To get things working I have tried both commenting parts of these 2 functions out or changing the order in which things are called, but either the error persists or I get different validation errors.
I also tried signaling the semaphore directly:
vk::SemaphoreSignalInfo semaphore_info = {};
semaphore_info.semaphore = *render_finished_sems[current_frame];
semaphore_info.value = 0;
device.signalSemaphore(semaphore_info);
But all I managed is to cause a segmentation fault
The error was the order of operations. This is wrong:
graphics_queue.waitIdle();
device.waitIdle();
vk::SwapchainKHR swap_chains[] = {*swap_chain};
vk::PresentInfoKHR present_info = {};
present_info.waitSemaphoreCount = 1;
present_info.pWaitSemaphores = signal_semaphores;
present_info.swapchainCount = 1;
present_info.pSwapchains = swap_chains;
present_info.pImageIndices = &active_image_index;
result = graphics_queue.presentKHR(&present_info);
current_frame = (current_frame + 1) % MAX_FRAMES_IN_FLIGHT;
This is the correct use:
vk::SwapchainKHR swap_chains[] = {*swap_chain};
vk::PresentInfoKHR present_info = {};
present_info.waitSemaphoreCount = 1;
present_info.pWaitSemaphores = signal_semaphores;
present_info.swapchainCount = 1;
present_info.pSwapchains = swap_chains;
present_info.pImageIndices = &active_image_index;
result = graphics_queue.presentKHR(&present_info);
current_frame = (current_frame + 1) % MAX_FRAMES_IN_FLIGHT;
graphics_queue.waitIdle();
device.waitIdle();
I've been getting a weird error when calling CreateGraphicsPipelineState().
The function returns E_INVALIDARG even though the description is all set up.
The description worked before and the I tried to add indexbuffers to my pipeline, I didn't even touch any of the code for PSO or Shaders and now the PSO creation is all messed up.
The issue is that I don't get any DX-error messages from the driver when enabling the debug-layer. I only get this
"Microsoft C++ exception: _com_error at memory location
when I step through the function.
It feels like it is some pointer error or similar, but I can't figure out what the error is. Perhaps anyone of you can see an obvious mistake that I made?
Here's my code:
CGraphicsPSO* pso = new CGraphicsPSO();
D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
// Input Layout
std::vector<D3D12_INPUT_ELEMENT_DESC> elements;
if (aPSODesc.inputLayout != nullptr)
{
auto& ilData = aPSODesc.inputLayout->desc;
for (auto& element : ilData)
{
// All Data here is correct when breaking
D3D12_INPUT_ELEMENT_DESC elementDesc;
elementDesc.SemanticName = element.mySemanticName;
elementDesc.SemanticIndex = element.mySemanticIndex;
elementDesc.InputSlot = element.myInputSlot;
elementDesc.AlignedByteOffset = element.myAlignedByteOffset;
elementDesc.InputSlotClass = _ConvertInputClassificationDX12(element.myInputSlotClass);
elementDesc.Format = _ConvertFormatDX12(element.myFormat);
elementDesc.InstanceDataStepRate = element.myInstanceDataStepRate;
elements.push_back(elementDesc);
}
D3D12_INPUT_LAYOUT_DESC inputLayout = {};
inputLayout.NumElements = (UINT)elements.size();
inputLayout.pInputElementDescs = elements.data();
psoDesc.InputLayout = inputLayout;
}
// TOPOLOGY
switch (aPSODesc.topology)
{
default:
case EPrimitiveTopology::TriangleList:
psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; // <--- Always this option
break;
case EPrimitiveTopology::PointList:
psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT;
break;
case EPrimitiveTopology::LineList:
psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE;
break;
//case EPrimitiveTopology::Patch:
// psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH;
// break;
}
// Shaders
if (aPSODesc.vs != nullptr)
{
D3D12_SHADER_BYTECODE vertexShaderBytecode = {};
vertexShaderBytecode.BytecodeLength = aPSODesc.vs->myByteCodeSize;
vertexShaderBytecode.pShaderBytecode = aPSODesc.vs->myByteCode;
psoDesc.VS = vertexShaderBytecode;
}
if (aPSODesc.ps != nullptr)
{
D3D12_SHADER_BYTECODE pixelShaderBytecode = {};
pixelShaderBytecode.BytecodeLength = aPSODesc.ps->myByteCodeSize;
pixelShaderBytecode.pShaderBytecode = aPSODesc.ps->myByteCode;
psoDesc.PS = pixelShaderBytecode;
}
psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM; // format of the render target
DXGI_SAMPLE_DESC sampleDesc = {};
sampleDesc.Count = 1;
sampleDesc.Quality = 0;
psoDesc.DepthStencilState.DepthEnable = FALSE;
psoDesc.DepthStencilState.StencilEnable = FALSE;
psoDesc.SampleDesc = sampleDesc; // must be the same sample description as the swapchain and depth/stencil buffer
psoDesc.SampleMask = UINT_MAX; // sample mask has to do with multi-sampling. 0xffffffff means point sampling is done
psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); // a default rasterizer state.
psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); // a default blent state.
psoDesc.NumRenderTargets = 1; // we are only binding one render target
psoDesc.pRootSignature = myGraphicsRootSignature;
psoDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;
ID3D12PipelineState* pipelineState;
HRESULT hr = myDevice->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&pipelineState));
pso->myPipelineState = pipelineState;
if (FAILED(hr))
{
delete pso;
return nullptr;
}
return pso;
So I just found the error.
It seems like the way I parsed my semantics for my input-layout gave me an invalid pointer.
Thus the memory at the adress was invalid and giving the DX12-device incorrect decriptions.
So what I did was to locally store the semantic-names within my CreatePSO function until the PSO was created, and now it all works.
Looks to me like the pointers to storage you promised are going out of scope.
..
D3D12_INPUT_LAYOUT_DESC inputLayout = {};
..
psoDesc.InputLayout = inputLayout;
}
auto featureReport = hidDevice->CreateFeatureReport(6);
auto dataWriter = ref new DataWriter();
Array<UINT8>^buff = ref new Array<UINT8>(6);
buff[0] = (uint8)featureReport->Id;
buff[1] = 0xe;//update mode
buff[2] = 0;
buff[3] = 0;
buff[4] = 0;
buff[5] = 0;
dataWriter->WriteBytes(buff);
featureReport->Data = dataWriter->DetachBuffer();
create_task(hidDevice->SendFeatureReportAsync(featureReport))
.then([this](task<uint32> bytesWrittenTask)
{
auto x = bytesWrittenTask.get(); // If exception occured, let an exception flow down the task chain so it can be caught
//MessageDialog^ msg = ref new MessageDialog(x.ToString());
});
This code is to access the hid driver after the success of the need to send commands to the hid device, but here the error featureReport-> Data = dataWriter-> DetachBuffer ();
Error Message: HRESULT: 0x80070057 Parameter Error
You are probably hitting an invalid buffer length. Try to get the buffer length, before you try to write to it.
(pseudo code)
FeatureReport report = hidDevice->GetFeatureReport(reportId)
Array<UINT8>^buff = ref new Array<UINT8>(report.Data.Length);
I'm running into an access violation on this piece of Vulkan API.
VkResult err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.billboard);
The error is:
Exception thrown at 0x00007FFB8BEDB276 (amdvlk64.dll) in 3Dfunctionvisualizer.exe: 0xC0000005: Access violation reading location 0x000000000000004C.
All other relevant code, as far as I can tell:
VkPipelineCacheCreateInfo pipelineCacheCreateInfo = {};
pipelineCacheCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
VkResult err = vkCreatePipelineCache(device, &pipelineCacheCreateInfo, nullptr, &pipelineCache);
VkPipelineInputAssemblyStateCreateInfo inputAssemblyState =
vkTools::initializers::pipelineInputAssemblyStateCreateInfo(
VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
0,
VK_FALSE);
VkPipelineRasterizationStateCreateInfo rasterizationState =
vkTools::initializers::pipelineRasterizationStateCreateInfo(
VK_POLYGON_MODE_FILL,
VK_CULL_MODE_BACK_BIT,
VK_FRONT_FACE_CLOCKWISE,
0);
VkPipelineColorBlendAttachmentState blendAttachmentState =
vkTools::initializers::pipelineColorBlendAttachmentState(
0xf,
VK_FALSE);
VkPipelineColorBlendStateCreateInfo colorBlendState =
vkTools::initializers::pipelineColorBlendStateCreateInfo(
1,
&blendAttachmentState);
VkPipelineDepthStencilStateCreateInfo depthStencilState =
vkTools::initializers::pipelineDepthStencilStateCreateInfo(
VK_TRUE,
VK_TRUE,
VK_COMPARE_OP_LESS_OR_EQUAL);
VkPipelineViewportStateCreateInfo viewportState =
vkTools::initializers::pipelineViewportStateCreateInfo(1, 1, 0);
VkPipelineMultisampleStateCreateInfo multisampleState =
vkTools::initializers::pipelineMultisampleStateCreateInfo(
VK_SAMPLE_COUNT_1_BIT,
0);
std::vector<VkDynamicState> dynamicStateEnables = {
VK_DYNAMIC_STATE_VIEWPORT,
VK_DYNAMIC_STATE_SCISSOR,
VK_DYNAMIC_STATE_LINE_WIDTH
};
VkPipelineDynamicStateCreateInfo dynamicState =
vkTools::initializers::pipelineDynamicStateCreateInfo(
dynamicStateEnables.data(),
dynamicStateEnables.size(),
0);
std::array<VkPipelineShaderStageCreateInfo, 3> shaderStages;
shaderStages[0] = loadShader("./../data/shaders/3DVisualizer/billboard.vert.spv", VK_SHADER_STAGE_VERTEX_BIT);
shaderStages[1] = loadShader("./../data/shaders/3DVisualizer/billboard.geom.spv", VK_SHADER_STAGE_GEOMETRY_BIT);
shaderStages[2] = loadShader("./../data/shaders/3DVisualizer/billboard.frag.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
VkGraphicsPipelineCreateInfo pipelineCreateInfo =
vkTools::initializers::pipelineCreateInfo(
pipelineLayout,
renderPass,
0);
pipelineCreateInfo.pVertexInputState = &vertices.billboard.inputState;
pipelineCreateInfo.pInputAssemblyState = &inputAssemblyState;
pipelineCreateInfo.pRasterizationState = &rasterizationState;
pipelineCreateInfo.pColorBlendState = &colorBlendState;
pipelineCreateInfo.pMultisampleState = &multisampleState;
pipelineCreateInfo.pViewportState = &viewportState;
pipelineCreateInfo.pDepthStencilState = &depthStencilState;
pipelineCreateInfo.pDynamicState = &dynamicState;
pipelineCreateInfo.stageCount = 3;
pipelineCreateInfo.pStages = shaderStages.data();
pipelineCreateInfo.renderPass = renderPass;
The device and pipelineCache are both set by the superclass, which was written by Sascha Willems and works for all of the examples he has created, so I don't expect the problem would be there. However, that really only leaves pipelineCreateInfo or pipelines.billboard as the potential source of the error.
Both of those are dealt with in the (almost exact) same way as the examples by Sascha in his examples, so I'm at a loss here.
EDIT: I found the problem. I had failed to specify the binding point for the sampler in my shader.
On OSX I'm creating an AUGraph for my audio system like so:
OSStatus result = NewAUGraph(&mGraph);
AUNode outputNode;
AudioComponentDescription outputDesc;
outputDesc.componentType = kAudioUnitType_Output;
outputDesc.componentSubType = kAudioUnitSubType_DefaultOutput;
outputDesc.componentManufacturer = kAudioUnitManufacturer_Apple;
outputDesc.componentFlags = 0;
outputDesc.componentFlagsMask = 0;
result = AUGraphAddNode(mGraph, &outputDesc, &outputNode);
AUNode converterNode;
AudioComponentDescription converterDesc;
converterDesc.componentType = kAudioUnitType_FormatConverter;
converterDesc.componentSubType = kAudioUnitSubType_AUConverter;
converterDesc.componentManufacturer = kAudioUnitManufacturer_Apple;
converterDesc.componentFlags = 0;
outputDesc.componentFlagsMask = 0;
result = AUGraphAddNode(mGraph, &converterDesc, &converterNode);
result = AUGraphConnectNodeInput(mGraph, converterNode, 0, outputNode, 0);
result = AUGraphOpen(mGraph);
...initialize graph, start graph, etc...
This all works fine, I can hear sound, etc. Later the system is shut down:
unsigned char isRunning = false;
AUGraphIsRunning(mGraph, &isRunning);
if (isRunning)
AUGraphStop(mGraph);
OSStatus result;
unsigned char isInitialized = false;
AUGraphIsInitialized(mGraph, &isInitialized);
if (isInitialized)
{
result = AUGraphUninitialize(mGraph);
}
result = DisposeAUGraph(mGraph);
Again, no problems here. However a short while after the first code block gets executed again when the system is restarted. On:
result = AUGraphOpen(mGraph);
"result" comes out as -2005 (badComponentType). Anyone know what causes this?
Calling AUGraphClose in the shutdown fixed this. Guess you can't have two open graphs with the same output unit in?