mirror of
https://github.com/KhronosGroup/Vulkan-Hpp
synced 2024-11-09 22:20:07 +00:00
Add samples ImmutableSampler, InitTexture, InputAttachment (#315)
+ slightly adjust some other samples.
This commit is contained in:
parent
d4ddb0a2cd
commit
d965a74cc0
@ -25,6 +25,7 @@ set(SOURCES
|
||||
11_InitShaders.cpp
|
||||
../utils/shaders.cpp
|
||||
../utils/utils.cpp
|
||||
../../glslang/StandAlone/ResourceLimits.cpp
|
||||
)
|
||||
|
||||
source_group(headers FILES ${HEADERS})
|
||||
|
@ -28,6 +28,7 @@ set(SOURCES
|
||||
../utils/math.cpp
|
||||
../utils/shaders.cpp
|
||||
../utils/utils.cpp
|
||||
../../glslang/StandAlone/ResourceLimits.cpp
|
||||
)
|
||||
|
||||
source_group(headers FILES ${HEADERS})
|
||||
|
@ -28,6 +28,7 @@ set(SOURCES
|
||||
../utils/math.cpp
|
||||
../utils/shaders.cpp
|
||||
../utils/utils.cpp
|
||||
../../glslang/StandAlone/ResourceLimits.cpp
|
||||
)
|
||||
|
||||
source_group(headers FILES ${HEADERS})
|
||||
|
@ -28,6 +28,7 @@ set(SOURCES
|
||||
../utils/math.cpp
|
||||
../utils/shaders.cpp
|
||||
../utils/utils.cpp
|
||||
../../glslang/StandAlone/ResourceLimits.cpp
|
||||
)
|
||||
|
||||
source_group(headers FILES ${HEADERS})
|
||||
|
@ -26,101 +26,6 @@
|
||||
static char const* AppName = "DrawTexturedCube";
|
||||
static char const* EngineName = "Vulkan.hpp";
|
||||
|
||||
// vertex shader with (P)osition and (T)exCoord in and (T)exCoord out
|
||||
const std::string vertexShaderText_PT_T = R"(
|
||||
#version 400
|
||||
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
#extension GL_ARB_shading_language_420pack : enable
|
||||
|
||||
layout (std140, binding = 0) uniform buffer
|
||||
{
|
||||
mat4 mvp;
|
||||
} uniformBuffer;
|
||||
|
||||
layout (location = 0) in vec4 pos;
|
||||
layout (location = 1) in vec2 inTexCoord;
|
||||
|
||||
layout (location = 0) out vec2 outTexCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
outTexCoord = inTexCoord;
|
||||
gl_Position = uniformBuffer.mvp * pos;
|
||||
}
|
||||
)";
|
||||
|
||||
// fragment shader with (T)exCoord in and (C)olor out
|
||||
const std::string fragmentShaderText_T_C = R"(
|
||||
#version 400
|
||||
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
#extension GL_ARB_shading_language_420pack : enable
|
||||
|
||||
layout (binding = 1) uniform sampler2D tex;
|
||||
|
||||
layout (location = 0) in vec2 inTexCoord;
|
||||
|
||||
layout (location = 0) out vec4 outColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
outColor = textureLod(tex, inTexCoord, 0.0f);
|
||||
}
|
||||
)";
|
||||
|
||||
struct VertexPT
|
||||
{
|
||||
float x, y, z, w; // Position data
|
||||
float u, v; // texture u,v
|
||||
};
|
||||
|
||||
static const VertexPT texturedCubeData[] =
|
||||
{
|
||||
// left face
|
||||
{ -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 0.0f },
|
||||
{ -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f },
|
||||
{ -1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f },
|
||||
{ -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f },
|
||||
{ -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 0.0f },
|
||||
{ -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f },
|
||||
// front face
|
||||
{ -1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f },
|
||||
{ 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 0.0f },
|
||||
{ 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f },
|
||||
{ -1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f },
|
||||
{ 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f },
|
||||
{ -1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f },
|
||||
// top face
|
||||
{ -1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 1.0f },
|
||||
{ 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f },
|
||||
{ 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f },
|
||||
{ -1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 1.0f },
|
||||
{ -1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f },
|
||||
{ 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 0.0f },
|
||||
// bottom face
|
||||
{ -1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f },
|
||||
{ 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f },
|
||||
{ -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f },
|
||||
{ -1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f },
|
||||
{ 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 0.0f },
|
||||
{ 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f },
|
||||
// right face
|
||||
{ 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f },
|
||||
{ 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f },
|
||||
{ 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f },
|
||||
{ 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f },
|
||||
{ 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f },
|
||||
{ 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f },
|
||||
// back face
|
||||
{ -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f },
|
||||
{ 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f },
|
||||
{ -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f },
|
||||
{ -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f },
|
||||
{ 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f },
|
||||
{ 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f },
|
||||
};
|
||||
|
||||
int main(int /*argc*/, char ** /*argv*/)
|
||||
{
|
||||
try
|
||||
|
@ -28,6 +28,7 @@ set(SOURCES
|
||||
../utils/math.cpp
|
||||
../utils/shaders.cpp
|
||||
../utils/utils.cpp
|
||||
../../glslang/StandAlone/ResourceLimits.cpp
|
||||
)
|
||||
|
||||
source_group(headers FILES ${HEADERS})
|
||||
|
@ -17,16 +17,11 @@ cmake_minimum_required(VERSION 3.2)
|
||||
project(Events)
|
||||
|
||||
set(HEADERS
|
||||
../utils/geometries.hpp
|
||||
../utils/math.hpp
|
||||
../utils/shaders.hpp
|
||||
../utils/utils.hpp
|
||||
)
|
||||
|
||||
set(SOURCES
|
||||
Events.cpp
|
||||
../utils/math.cpp
|
||||
../utils/shaders.cpp
|
||||
../utils/utils.cpp
|
||||
)
|
||||
|
||||
|
@ -15,9 +15,6 @@
|
||||
// VulkanHpp Samples : Events
|
||||
// Use basic events
|
||||
|
||||
#include "../utils/geometries.hpp"
|
||||
#include "../utils/math.hpp"
|
||||
#include "../utils/shaders.hpp"
|
||||
#include "../utils/utils.hpp"
|
||||
#include "vulkan/vulkan.hpp"
|
||||
#include "SPIRV/GlslangToSpv.h"
|
||||
@ -84,7 +81,7 @@ int main(int /*argc*/, char ** /*argv*/)
|
||||
device->resetFences(fence.get());
|
||||
|
||||
// Note that stepping through this code in the debugger is a bad idea because the GPU can TDR waiting for the event.
|
||||
// Execute the code from vkQueueSubmit through vkSetEvent without breakpoints
|
||||
// Execute the code from vk::Queue::submit() through vk::Device::setEvent() without breakpoints
|
||||
waitDestinationStageMask = vk::PipelineStageFlagBits::eBottomOfPipe;
|
||||
graphicsQueue.submit(submitInfo, fence.get());
|
||||
|
||||
@ -92,7 +89,7 @@ int main(int /*argc*/, char ** /*argv*/)
|
||||
result = device->waitForFences(fence.get(), true, vk::su::FenceTimeout);
|
||||
if (result != vk::Result::eTimeout)
|
||||
{
|
||||
std::cout << "Didn't get expected timeout in vkWaitForFences, exiting\n";
|
||||
std::cout << "Didn't get expected timeout in vk::Device::waitForFences, exiting\n";
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
@ -114,7 +111,7 @@ int main(int /*argc*/, char ** /*argv*/)
|
||||
commandBuffers[0]->setEvent(event.get(), vk::PipelineStageFlagBits::eBottomOfPipe);
|
||||
commandBuffers[0]->end();
|
||||
|
||||
// Look for the event on the CPU. It should be RESET since we haven't sent the command buffer yet.
|
||||
// Look for the event on the CPU. It should be vk::Result::eEventReset since we haven't sent the command buffer yet.
|
||||
result = device->getEventStatus(event.get());
|
||||
assert(result == vk::Result::eEventReset);
|
||||
|
||||
|
45
samples/ImmutableSampler/CMakeLists.txt
Normal file
45
samples/ImmutableSampler/CMakeLists.txt
Normal file
@ -0,0 +1,45 @@
|
||||
# Copyright(c) 2019, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
cmake_minimum_required(VERSION 3.2)
|
||||
|
||||
project(ImmutableSampler)
|
||||
|
||||
set(HEADERS
|
||||
../utils/geometries.hpp
|
||||
../utils/math.hpp
|
||||
../utils/shaders.hpp
|
||||
../utils/utils.hpp
|
||||
)
|
||||
|
||||
set(SOURCES
|
||||
ImmutableSampler.cpp
|
||||
../utils/math.cpp
|
||||
../utils/shaders.cpp
|
||||
../utils/utils.cpp
|
||||
../../glslang/StandAlone/ResourceLimits.cpp
|
||||
)
|
||||
|
||||
source_group(headers FILES ${HEADERS})
|
||||
source_group(sources FILES ${SOURCES})
|
||||
|
||||
add_executable(ImmutableSampler
|
||||
${HEADERS}
|
||||
${SOURCES}
|
||||
)
|
||||
|
||||
set_target_properties(ImmutableSampler PROPERTIES FOLDER "Samples")
|
||||
target_include_directories(ImmutableSampler PUBLIC ${CMAKE_SOURCE_DIR}/glslang)
|
||||
target_link_libraries(ImmutableSampler PUBLIC glslang SPIRV "$ENV{VULKAN_SDK}/Lib/vulkan-1.lib"
|
||||
)
|
168
samples/ImmutableSampler/ImmutableSampler.cpp
Normal file
168
samples/ImmutableSampler/ImmutableSampler.cpp
Normal file
@ -0,0 +1,168 @@
|
||||
// Copyright(c) 2019, NVIDIA CORPORATION. All rights reserved.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// VulkanHpp Samples : ImmutableSampler
|
||||
// Use an immutable sampler to texture a cube.
|
||||
|
||||
#include "../utils/geometries.hpp"
|
||||
#include "../utils/math.hpp"
|
||||
#include "../utils/shaders.hpp"
|
||||
#include "../utils/utils.hpp"
|
||||
#include "vulkan/vulkan.hpp"
|
||||
#include "SPIRV/GlslangToSpv.h"
|
||||
#include <iostream>
|
||||
|
||||
static char const* AppName = "ImmutableSampler";
|
||||
static char const* EngineName = "Vulkan.hpp";
|
||||
|
||||
int main(int /*argc*/, char ** /*argv*/)
|
||||
{
|
||||
try
|
||||
{
|
||||
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, vk::su::getInstanceExtensions());
|
||||
#if !defined(NDEBUG)
|
||||
vk::UniqueDebugReportCallbackEXT debugReportCallback = vk::su::createDebugReportCallback(instance);
|
||||
#endif
|
||||
|
||||
std::vector<vk::PhysicalDevice> physicalDevices = instance->enumeratePhysicalDevices();
|
||||
assert(!physicalDevices.empty());
|
||||
|
||||
vk::su::SurfaceData surfaceData(instance, AppName, AppName, vk::Extent2D(500, 500));
|
||||
|
||||
std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevices[0], surfaceData.surface);
|
||||
vk::UniqueDevice device = vk::su::createDevice(physicalDevices[0], graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions());
|
||||
|
||||
vk::UniqueCommandPool commandPool = vk::su::createCommandPool(device, graphicsAndPresentQueueFamilyIndex.first);
|
||||
std::vector<vk::UniqueCommandBuffer> commandBuffers = device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(commandPool.get(), vk::CommandBufferLevel::ePrimary, 1));
|
||||
|
||||
vk::Queue graphicsQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.first, 0);
|
||||
vk::Queue presentQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.second, 0);
|
||||
|
||||
vk::su::SwapChainData swapChainData(physicalDevices[0], device, surfaceData.surface, surfaceData.extent, vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc
|
||||
, graphicsAndPresentQueueFamilyIndex.first, graphicsAndPresentQueueFamilyIndex.second);
|
||||
|
||||
vk::su::DepthBufferData depthBufferData(physicalDevices[0], device, vk::Format::eD16Unorm, surfaceData.extent);
|
||||
|
||||
vk::su::BufferData uniformBufferData(physicalDevices[0], device, sizeof(glm::mat4x4), vk::BufferUsageFlagBits::eUniformBuffer);
|
||||
vk::su::copyToDevice(device, uniformBufferData.deviceMemory, vk::su::createModelViewProjectionClipMatrix());
|
||||
|
||||
vk::UniqueRenderPass renderPass = vk::su::createRenderPass(device, vk::su::pickColorFormat(physicalDevices[0].getSurfaceFormatsKHR(surfaceData.surface.get())), depthBufferData.format);
|
||||
|
||||
glslang::InitializeProcess();
|
||||
vk::UniqueShaderModule vertexShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eVertex, vertexShaderText_PT_T);
|
||||
vk::UniqueShaderModule fragmentShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText_T_C);
|
||||
glslang::FinalizeProcess();
|
||||
|
||||
std::vector<vk::UniqueFramebuffer> framebuffers = vk::su::createFramebuffers(device, renderPass, swapChainData.imageViews, depthBufferData.imageView, surfaceData.extent);
|
||||
|
||||
vk::su::BufferData vertexBufferData(physicalDevices[0], device, sizeof(texturedCubeData), vk::BufferUsageFlagBits::eVertexBuffer);
|
||||
vk::su::copyToDevice(device, vertexBufferData.deviceMemory, texturedCubeData, sizeof(texturedCubeData) / sizeof(texturedCubeData[0]));
|
||||
|
||||
/* VULKAN_KEY_START */
|
||||
|
||||
vk::su::TextureData textureData(physicalDevices[0], device);
|
||||
|
||||
commandBuffers[0]->begin(vk::CommandBufferBeginInfo());
|
||||
textureData.setCheckerboardTexture(device, commandBuffers[0]);
|
||||
|
||||
vk::DescriptorSetLayoutBinding bindings[2] =
|
||||
{
|
||||
vk::DescriptorSetLayoutBinding(0, vk::DescriptorType::eUniformBuffer, 1, vk::ShaderStageFlagBits::eVertex),
|
||||
vk::DescriptorSetLayoutBinding(1, vk::DescriptorType::eCombinedImageSampler, 1, vk::ShaderStageFlagBits::eFragment, &textureData.textureSampler.get())
|
||||
};
|
||||
vk::UniqueDescriptorSetLayout descriptorSetLayout = device->createDescriptorSetLayoutUnique(vk::DescriptorSetLayoutCreateInfo(vk::DescriptorSetLayoutCreateFlags(), 2, bindings));
|
||||
|
||||
// Create pipeline layout
|
||||
vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get()));
|
||||
|
||||
// Create a single pool to contain data for our descriptor set
|
||||
vk::DescriptorPoolSize poolSizes[2] =
|
||||
{
|
||||
vk::DescriptorPoolSize(vk::DescriptorType::eUniformBuffer, 1),
|
||||
vk::DescriptorPoolSize(vk::DescriptorType::eCombinedImageSampler, 1)
|
||||
};
|
||||
vk::UniqueDescriptorPool descriptorPool = device->createDescriptorPoolUnique(vk::DescriptorPoolCreateInfo(vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet, 1, 2, poolSizes));
|
||||
|
||||
// Populate descriptor sets
|
||||
std::vector<vk::UniqueDescriptorSet> descriptorSets = device->allocateDescriptorSetsUnique(vk::DescriptorSetAllocateInfo(descriptorPool.get(), 1, &descriptorSetLayout.get()));
|
||||
|
||||
vk::DescriptorBufferInfo bufferInfo(uniformBufferData.buffer.get(), 0, sizeof(glm::mat4x4));
|
||||
vk::DescriptorImageInfo imageInfo(textureData.textureSampler.get(), textureData.imageData->imageView.get(), vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||
vk::WriteDescriptorSet writeDescriptorSets[2] =
|
||||
{
|
||||
vk::WriteDescriptorSet(descriptorSets[0].get(), 0, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &bufferInfo),
|
||||
vk::WriteDescriptorSet(descriptorSets[0].get(), 1, 0, 1, vk::DescriptorType::eCombinedImageSampler, &imageInfo)
|
||||
};
|
||||
device->updateDescriptorSets(vk::ArrayProxy<const vk::WriteDescriptorSet>(2, writeDescriptorSets), nullptr);
|
||||
|
||||
/* VULKAN_KEY_END */
|
||||
|
||||
vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique(vk::PipelineCacheCreateInfo());
|
||||
vk::UniquePipeline graphicsPipeline = vk::su::createGraphicsPipeline(device, pipelineCache, vertexShaderModule, fragmentShaderModule, sizeof(texturedCubeData[0]), pipelineLayout, renderPass);
|
||||
|
||||
vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique(vk::SemaphoreCreateInfo());
|
||||
vk::ResultValue<uint32_t> currentBuffer = device->acquireNextImageKHR(swapChainData.swapChain.get(), vk::su::FenceTimeout, imageAcquiredSemaphore.get(), nullptr);
|
||||
assert(currentBuffer.result == vk::Result::eSuccess);
|
||||
assert(currentBuffer.value < framebuffers.size());
|
||||
|
||||
vk::ClearValue clearValues[2];
|
||||
clearValues[0].color = vk::ClearColorValue(std::array<float, 4>({ 0.2f, 0.2f, 0.2f, 0.2f }));
|
||||
clearValues[1].depthStencil = vk::ClearDepthStencilValue(1.0f, 0);
|
||||
vk::RenderPassBeginInfo renderPassBeginInfo(renderPass.get(), framebuffers[currentBuffer.value].get(), vk::Rect2D(vk::Offset2D(0, 0), surfaceData.extent), 2, clearValues);
|
||||
commandBuffers[0]->beginRenderPass(renderPassBeginInfo, vk::SubpassContents::eInline);
|
||||
commandBuffers[0]->bindPipeline(vk::PipelineBindPoint::eGraphics, graphicsPipeline.get());
|
||||
commandBuffers[0]->bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, descriptorSets[0].get(), nullptr);
|
||||
|
||||
vk::DeviceSize offset = 0;
|
||||
commandBuffers[0]->bindVertexBuffers(0, vertexBufferData.buffer.get(), offset);
|
||||
|
||||
vk::Viewport viewport(0.0f, 0.0f, static_cast<float>(surfaceData.extent.width), static_cast<float>(surfaceData.extent.height), 0.0f, 1.0f);
|
||||
commandBuffers[0]->setViewport(0, viewport);
|
||||
|
||||
vk::Rect2D scissor(vk::Offset2D(0, 0), surfaceData.extent);
|
||||
commandBuffers[0]->setScissor(0, scissor);
|
||||
|
||||
commandBuffers[0]->draw(12 * 3, 1, 0, 0);
|
||||
commandBuffers[0]->endRenderPass();
|
||||
commandBuffers[0]->end();
|
||||
|
||||
vk::su::submitAndWait(device, graphicsQueue, commandBuffers[0]);
|
||||
|
||||
presentQueue.presentKHR(vk::PresentInfoKHR(0, nullptr, 1, &swapChainData.swapChain.get(), ¤tBuffer.value));
|
||||
Sleep(1000);
|
||||
|
||||
device->waitIdle();
|
||||
#if defined(VK_USE_PLATFORM_WIN32_KHR)
|
||||
DestroyWindow(surfaceData.window);
|
||||
#else
|
||||
#pragma error "unhandled platform"
|
||||
#endif
|
||||
}
|
||||
catch (vk::SystemError err)
|
||||
{
|
||||
std::cout << "vk::SystemError: " << err.what() << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
catch (std::runtime_error err)
|
||||
{
|
||||
std::cout << "std::runtime_error: " << err.what() << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::cout << "unknown error\n";
|
||||
exit(-1);
|
||||
}
|
||||
return 0;
|
||||
}
|
45
samples/InitTexture/CMakeLists.txt
Normal file
45
samples/InitTexture/CMakeLists.txt
Normal file
@ -0,0 +1,45 @@
|
||||
# Copyright(c) 2019, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
cmake_minimum_required(VERSION 3.2)
|
||||
|
||||
project(InitTexture)
|
||||
|
||||
set(HEADERS
|
||||
../utils/geometries.hpp
|
||||
../utils/math.hpp
|
||||
../utils/shaders.hpp
|
||||
../utils/utils.hpp
|
||||
)
|
||||
|
||||
set(SOURCES
|
||||
InitTexture.cpp
|
||||
../utils/math.cpp
|
||||
../utils/shaders.cpp
|
||||
../utils/utils.cpp
|
||||
../../glslang/StandAlone/ResourceLimits.cpp
|
||||
)
|
||||
|
||||
source_group(headers FILES ${HEADERS})
|
||||
source_group(sources FILES ${SOURCES})
|
||||
|
||||
add_executable(InitTexture
|
||||
${HEADERS}
|
||||
${SOURCES}
|
||||
)
|
||||
|
||||
set_target_properties(InitTexture PROPERTIES FOLDER "Samples")
|
||||
target_include_directories(InitTexture PUBLIC ${CMAKE_SOURCE_DIR}/glslang)
|
||||
target_link_libraries(InitTexture PUBLIC glslang SPIRV "$ENV{VULKAN_SDK}/Lib/vulkan-1.lib"
|
||||
)
|
166
samples/InitTexture/InitTexture.cpp
Normal file
166
samples/InitTexture/InitTexture.cpp
Normal file
@ -0,0 +1,166 @@
|
||||
// Copyright(c) 2019, NVIDIA CORPORATION. All rights reserved.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// VulkanHpp Samples : InitTexture
|
||||
// Initialize texture
|
||||
|
||||
#include "../utils/geometries.hpp"
|
||||
#include "../utils/math.hpp"
|
||||
#include "../utils/shaders.hpp"
|
||||
#include "../utils/utils.hpp"
|
||||
#include "vulkan/vulkan.hpp"
|
||||
#include "SPIRV/GlslangToSpv.h"
|
||||
#include <iostream>
|
||||
|
||||
static char const* AppName = "InitTexture";
|
||||
static char const* EngineName = "Vulkan.hpp";
|
||||
|
||||
int main(int /*argc*/, char ** /*argv*/)
|
||||
{
|
||||
try
|
||||
{
|
||||
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, vk::su::getInstanceExtensions());
|
||||
#if !defined(NDEBUG)
|
||||
vk::UniqueDebugReportCallbackEXT debugReportCallback = vk::su::createDebugReportCallback(instance);
|
||||
#endif
|
||||
|
||||
std::vector<vk::PhysicalDevice> physicalDevices = instance->enumeratePhysicalDevices();
|
||||
assert(!physicalDevices.empty());
|
||||
|
||||
vk::su::SurfaceData surfaceData(instance, AppName, AppName, vk::Extent2D(50, 50));
|
||||
|
||||
std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevices[0], surfaceData.surface);
|
||||
vk::UniqueDevice device = vk::su::createDevice(physicalDevices[0], graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions());
|
||||
|
||||
vk::UniqueCommandPool commandPool = vk::su::createCommandPool(device, graphicsAndPresentQueueFamilyIndex.first);
|
||||
std::vector<vk::UniqueCommandBuffer> commandBuffers = device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(commandPool.get(), vk::CommandBufferLevel::ePrimary, 1));
|
||||
|
||||
vk::Queue graphicsQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.first, 0);
|
||||
vk::Queue presentQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.second, 0);
|
||||
|
||||
/* VULKAN_KEY_START */
|
||||
|
||||
vk::Format format = vk::Format::eR8G8B8A8Unorm;
|
||||
vk::FormatProperties formatProperties = physicalDevices[0].getFormatProperties(format);
|
||||
|
||||
// See if we can use a linear tiled image for a texture, if not, we will need a staging buffer for the texture data
|
||||
bool needsStaging = !(formatProperties.linearTilingFeatures & vk::FormatFeatureFlagBits::eSampledImage);
|
||||
|
||||
vk::UniqueImage image = device->createImageUnique(vk::ImageCreateInfo(vk::ImageCreateFlags(), vk::ImageType::e2D, format, vk::Extent3D(surfaceData.extent, 1), 1, 1,
|
||||
vk::SampleCountFlagBits::e1, needsStaging ? vk::ImageTiling::eOptimal : vk::ImageTiling::eLinear,
|
||||
vk::ImageUsageFlagBits::eSampled | (needsStaging ? vk::ImageUsageFlagBits::eTransferDst : vk::ImageUsageFlagBits()),
|
||||
vk::SharingMode::eExclusive, 0, nullptr, needsStaging ? vk::ImageLayout::eUndefined : vk::ImageLayout::ePreinitialized));
|
||||
|
||||
vk::MemoryRequirements memoryRequirements = device->getImageMemoryRequirements(image.get());
|
||||
uint32_t memoryTypeIndex = vk::su::findMemoryType(physicalDevices[0].getMemoryProperties(), memoryRequirements.memoryTypeBits,
|
||||
needsStaging ? vk::MemoryPropertyFlags() : (vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent));
|
||||
|
||||
// allocate memory
|
||||
vk::UniqueDeviceMemory imageMemory = device->allocateMemoryUnique(vk::MemoryAllocateInfo(memoryRequirements.size, memoryTypeIndex));
|
||||
|
||||
// bind memory
|
||||
device->bindImageMemory(image.get(), imageMemory.get(), 0);
|
||||
|
||||
vk::UniqueBuffer textureBuffer;
|
||||
vk::UniqueDeviceMemory textureBufferMemory;
|
||||
if (needsStaging)
|
||||
{
|
||||
// Need a staging buffer to map and copy texture into
|
||||
textureBuffer = device->createBufferUnique(vk::BufferCreateInfo(vk::BufferCreateFlags(), surfaceData.extent.width * surfaceData.extent.height * 4, vk::BufferUsageFlagBits::eTransferSrc));
|
||||
|
||||
memoryRequirements = device->getBufferMemoryRequirements(textureBuffer.get());
|
||||
memoryTypeIndex = vk::su::findMemoryType(physicalDevices[0].getMemoryProperties(), memoryRequirements.memoryTypeBits, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent);
|
||||
|
||||
// allocate memory
|
||||
textureBufferMemory = device->allocateMemoryUnique(vk::MemoryAllocateInfo(memoryRequirements.size, memoryTypeIndex));
|
||||
|
||||
// bind memory
|
||||
device->bindBufferMemory(textureBuffer.get(), textureBufferMemory.get(), 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
vk::SubresourceLayout subresourceLayout = device->getImageSubresourceLayout(image.get(), vk::ImageSubresource(vk::ImageAspectFlagBits::eColor));
|
||||
}
|
||||
|
||||
void* data = device->mapMemory(needsStaging ? textureBufferMemory.get() : imageMemory.get(), 0, memoryRequirements.size, vk::MemoryMapFlags());
|
||||
|
||||
// Checkerboard of 16x16 pixel squares
|
||||
unsigned char *pImageMemory = static_cast<unsigned char*>(data);
|
||||
for (uint32_t row = 0; row < surfaceData.extent.height; row++)
|
||||
{
|
||||
for (uint32_t col = 0; col < surfaceData.extent.width; col++)
|
||||
{
|
||||
unsigned char rgb = (((row & 0x10) == 0) ^ ((col & 0x10) == 0)) * 255;
|
||||
pImageMemory[0] = rgb;
|
||||
pImageMemory[1] = rgb;
|
||||
pImageMemory[2] = rgb;
|
||||
pImageMemory[3] = 255;
|
||||
pImageMemory += 4;
|
||||
}
|
||||
}
|
||||
|
||||
device->unmapMemory(needsStaging ? textureBufferMemory.get() : imageMemory.get());
|
||||
|
||||
commandBuffers[0]->begin(vk::CommandBufferBeginInfo());
|
||||
if (needsStaging)
|
||||
{
|
||||
// Since we're going to blit to the texture image, set its layout to eTransferDstOptimal
|
||||
vk::su::setImageLayout(commandBuffers[0], image.get(), vk::ImageAspectFlagBits::eColor, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal, vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer);
|
||||
vk::BufferImageCopy copyRegion(0, surfaceData.extent.width, surfaceData.extent.height, vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1), vk::Offset3D(0, 0, 0), vk::Extent3D(surfaceData.extent, 1));
|
||||
commandBuffers[0]->copyBufferToImage(textureBuffer.get(), image.get(), vk::ImageLayout::eTransferDstOptimal, copyRegion);
|
||||
// Set the layout for the texture image from eTransferDstOptimal to SHADER_READ_ONLY
|
||||
vk::su::setImageLayout(commandBuffers[0], image.get(), vk::ImageAspectFlagBits::eColor, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal, vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eFragmentShader);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we can use the linear tiled image as a texture, just do it
|
||||
vk::su::setImageLayout(commandBuffers[0], image.get(), vk::ImageAspectFlagBits::eColor, vk::ImageLayout::ePreinitialized, vk::ImageLayout::eShaderReadOnlyOptimal, vk::PipelineStageFlagBits::eHost, vk::PipelineStageFlagBits::eFragmentShader);
|
||||
}
|
||||
|
||||
commandBuffers[0]->end();
|
||||
vk::su::submitAndWait(device, graphicsQueue, commandBuffers[0]);
|
||||
|
||||
vk::UniqueSampler sampler = device->createSamplerUnique(vk::SamplerCreateInfo(vk::SamplerCreateFlags(), vk::Filter::eNearest, vk::Filter::eNearest, vk::SamplerMipmapMode::eNearest,
|
||||
vk::SamplerAddressMode::eClampToEdge, vk::SamplerAddressMode::eClampToEdge, vk::SamplerAddressMode::eClampToEdge, 0.0f, false, 1.0f, false, vk::CompareOp::eNever, 0.0f, 0.0f,
|
||||
vk::BorderColor::eFloatOpaqueWhite));
|
||||
|
||||
vk::ComponentMapping componentMapping(vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eG, vk::ComponentSwizzle::eB, vk::ComponentSwizzle::eA);
|
||||
vk::ImageViewCreateInfo imageViewCreateInfo(vk::ImageViewCreateFlags(), image.get(), vk::ImageViewType::e2D, format, componentMapping, vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1));
|
||||
vk::UniqueImageView imageView = device->createImageViewUnique(imageViewCreateInfo);
|
||||
|
||||
/* VULKAN_KEY_END */
|
||||
|
||||
#if defined(VK_USE_PLATFORM_WIN32_KHR)
|
||||
DestroyWindow(surfaceData.window);
|
||||
#else
|
||||
#pragma error "unhandled platform"
|
||||
#endif
|
||||
}
|
||||
catch (vk::SystemError err)
|
||||
{
|
||||
std::cout << "vk::SystemError: " << err.what() << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
catch (std::runtime_error err)
|
||||
{
|
||||
std::cout << "std::runtime_error: " << err.what() << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::cout << "unknown error\n";
|
||||
exit(-1);
|
||||
}
|
||||
return 0;
|
||||
}
|
45
samples/InputAttachment/CMakeLists.txt
Normal file
45
samples/InputAttachment/CMakeLists.txt
Normal file
@ -0,0 +1,45 @@
|
||||
# Copyright(c) 2019, NVIDIA CORPORATION. All rights reserved.
|
||||
#
|
||||
# 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.
|
||||
|
||||
cmake_minimum_required(VERSION 3.2)
|
||||
|
||||
project(InputAttachment)
|
||||
|
||||
set(HEADERS
|
||||
../utils/geometries.hpp
|
||||
../utils/math.hpp
|
||||
../utils/shaders.hpp
|
||||
../utils/utils.hpp
|
||||
)
|
||||
|
||||
set(SOURCES
|
||||
InputAttachment.cpp
|
||||
../utils/math.cpp
|
||||
../utils/shaders.cpp
|
||||
../utils/utils.cpp
|
||||
../../glslang/StandAlone/ResourceLimits.cpp
|
||||
)
|
||||
|
||||
source_group(headers FILES ${HEADERS})
|
||||
source_group(sources FILES ${SOURCES})
|
||||
|
||||
add_executable(InputAttachment
|
||||
${HEADERS}
|
||||
${SOURCES}
|
||||
)
|
||||
|
||||
set_target_properties(InputAttachment PROPERTIES FOLDER "Samples")
|
||||
target_include_directories(InputAttachment PUBLIC ${CMAKE_SOURCE_DIR}/glslang)
|
||||
target_link_libraries(InputAttachment PUBLIC glslang SPIRV "$ENV{VULKAN_SDK}/Lib/vulkan-1.lib"
|
||||
)
|
211
samples/InputAttachment/InputAttachment.cpp
Normal file
211
samples/InputAttachment/InputAttachment.cpp
Normal file
@ -0,0 +1,211 @@
|
||||
// Copyright(c) 2019, NVIDIA CORPORATION. All rights reserved.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// VulkanHpp Samples : InputAttachment
|
||||
// Use an input attachment to draw a yellow triangle
|
||||
|
||||
#include "../utils/geometries.hpp"
|
||||
#include "../utils/math.hpp"
|
||||
#include "../utils/shaders.hpp"
|
||||
#include "../utils/utils.hpp"
|
||||
#include "vulkan/vulkan.hpp"
|
||||
#include "SPIRV/GlslangToSpv.h"
|
||||
#include <iostream>
|
||||
|
||||
static char const* AppName = "InputAttachment";
|
||||
static char const* EngineName = "Vulkan.hpp";
|
||||
|
||||
static std::string vertexShaderText = R"(
|
||||
#version 450
|
||||
|
||||
vec2 vertices[3];
|
||||
|
||||
void main()
|
||||
{
|
||||
vertices[0] = vec2(-1.0f, -1.0f);
|
||||
vertices[1] = vec2( 1.0f, -1.0f);
|
||||
vertices[2] = vec2( 0.0f, 1.0f);
|
||||
|
||||
gl_Position = vec4(vertices[gl_VertexIndex % 3], 0.0f, 1.0f);
|
||||
}
|
||||
)";
|
||||
|
||||
// Use subpassLoad to read from input attachment
|
||||
static const char *fragmentShaderText = R"(
|
||||
#version 450
|
||||
|
||||
layout (input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput inputAttachment;
|
||||
|
||||
layout (location = 0) out vec4 outColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
outColor = subpassLoad(inputAttachment);
|
||||
}
|
||||
)";
|
||||
int main(int /*argc*/, char ** /*argv*/)
|
||||
{
|
||||
try
|
||||
{
|
||||
vk::UniqueInstance instance = vk::su::createInstance(AppName, EngineName, vk::su::getInstanceExtensions());
|
||||
#if !defined(NDEBUG)
|
||||
vk::UniqueDebugReportCallbackEXT debugReportCallback = vk::su::createDebugReportCallback(instance);
|
||||
#endif
|
||||
|
||||
std::vector<vk::PhysicalDevice> physicalDevices = instance->enumeratePhysicalDevices();
|
||||
assert(!physicalDevices.empty());
|
||||
|
||||
vk::FormatProperties formatProperties = physicalDevices[0].getFormatProperties(vk::Format::eR8G8B8A8Unorm);
|
||||
if (!(formatProperties.optimalTilingFeatures & vk::FormatFeatureFlagBits::eColorAttachment))
|
||||
{
|
||||
std::cout << "vk::Format::eR8G8B8A8Unorm format unsupported for input attachment\n";
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
vk::su::SurfaceData surfaceData(instance, AppName, AppName, vk::Extent2D(500, 500));
|
||||
|
||||
std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex(physicalDevices[0], surfaceData.surface);
|
||||
vk::UniqueDevice device = vk::su::createDevice(physicalDevices[0], graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions());
|
||||
|
||||
vk::UniqueCommandPool commandPool = vk::su::createCommandPool(device, graphicsAndPresentQueueFamilyIndex.first);
|
||||
std::vector<vk::UniqueCommandBuffer> commandBuffers = device->allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(commandPool.get(), vk::CommandBufferLevel::ePrimary, 1));
|
||||
|
||||
vk::Queue graphicsQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.first, 0);
|
||||
vk::Queue presentQueue = device->getQueue(graphicsAndPresentQueueFamilyIndex.second, 0);
|
||||
|
||||
vk::su::SwapChainData swapChainData(physicalDevices[0], device, surfaceData.surface, surfaceData.extent, vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferSrc,
|
||||
graphicsAndPresentQueueFamilyIndex.first, graphicsAndPresentQueueFamilyIndex.second);
|
||||
|
||||
/* VULKAN_KEY_START */
|
||||
|
||||
// Create a framebuffer with 2 attachments, one the color attachment the shaders render into, and the other an input attachment which
|
||||
// will be cleared to yellow, and then used by the shaders to color the drawn triangle. Final result should be a yellow triangle
|
||||
|
||||
// Create the image that will be used as the input attachment
|
||||
// The image for the color attachment is the presentable image already created as part of the SwapChainData
|
||||
vk::UniqueImage inputImage = device->createImageUnique(vk::ImageCreateInfo(vk::ImageCreateFlags(), vk::ImageType::e2D, swapChainData.colorFormat, vk::Extent3D(surfaceData.extent, 1), 1, 1,
|
||||
vk::SampleCountFlagBits::e1, vk::ImageTiling::eOptimal, vk::ImageUsageFlagBits::eInputAttachment | vk::ImageUsageFlagBits::eTransferDst));
|
||||
|
||||
vk::MemoryRequirements memoryRequirements = device->getImageMemoryRequirements(inputImage.get());
|
||||
uint32_t memoryTypeIndex = vk::su::findMemoryType(physicalDevices[0].getMemoryProperties(), memoryRequirements.memoryTypeBits, vk::MemoryPropertyFlags());
|
||||
vk::UniqueDeviceMemory inputMemory = device->allocateMemoryUnique(vk::MemoryAllocateInfo(memoryRequirements.size, memoryTypeIndex));
|
||||
device->bindImageMemory(inputImage.get(), inputMemory.get(), 0);
|
||||
|
||||
// Set the image layout to TRANSFER_DST_OPTIMAL to be ready for clear
|
||||
commandBuffers[0]->begin(vk::CommandBufferBeginInfo());
|
||||
vk::su::setImageLayout(commandBuffers[0], inputImage.get(), vk::ImageAspectFlagBits::eColor, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal,
|
||||
vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer);
|
||||
|
||||
commandBuffers[0]->clearColorImage(inputImage.get(), vk::ImageLayout::eTransferDstOptimal, vk::ClearColorValue(std::array<float, 4>({ {1.0f, 1.0f, 0.0f, 0.0f} })),
|
||||
vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS));
|
||||
|
||||
// Set the image layout to SHADER_READONLY_OPTIMAL for use by the shaders
|
||||
vk::su::setImageLayout(commandBuffers[0], inputImage.get(), vk::ImageAspectFlagBits::eColor, vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal,
|
||||
vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eFragmentShader);
|
||||
|
||||
vk::ComponentMapping componentMapping(vk::ComponentSwizzle::eR, vk::ComponentSwizzle::eG, vk::ComponentSwizzle::eB, vk::ComponentSwizzle::eA);
|
||||
vk::ImageViewCreateInfo imageViewCreateInfo(vk::ImageViewCreateFlags(), inputImage.get(), vk::ImageViewType::e2D, swapChainData.colorFormat, componentMapping, vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1));
|
||||
vk::UniqueImageView inputAttachmentView = device->createImageViewUnique(imageViewCreateInfo);
|
||||
|
||||
vk::DescriptorSetLayoutBinding layoutBinding(0, vk::DescriptorType::eInputAttachment, 1, vk::ShaderStageFlagBits::eFragment);
|
||||
vk::UniqueDescriptorSetLayout descriptorSetLayout = device->createDescriptorSetLayoutUnique(vk::DescriptorSetLayoutCreateInfo(vk::DescriptorSetLayoutCreateFlags(), 1, &layoutBinding));
|
||||
|
||||
vk::UniquePipelineLayout pipelineLayout = device->createPipelineLayoutUnique(vk::PipelineLayoutCreateInfo(vk::PipelineLayoutCreateFlags(), 1, &descriptorSetLayout.get()));
|
||||
|
||||
vk::AttachmentDescription attachments[2] =
|
||||
{
|
||||
// First attachment is the color attachment - clear at the beginning of the renderpass and transition layout to PRESENT_SRC_KHR at the end of renderpass
|
||||
vk::AttachmentDescription(vk::AttachmentDescriptionFlags(), swapChainData.colorFormat, vk::SampleCountFlagBits::e1, vk::AttachmentLoadOp::eClear, vk::AttachmentStoreOp::eStore,
|
||||
vk::AttachmentLoadOp::eDontCare, vk::AttachmentStoreOp::eDontCare, vk::ImageLayout::eUndefined, vk::ImageLayout::ePresentSrcKHR),
|
||||
// Second attachment is input attachment. Once cleared it should have width*height yellow pixels.
|
||||
// Doing a subpassLoad in the fragment shader should give the shader the color at the fragments x,y location from the input attachment
|
||||
vk::AttachmentDescription(vk::AttachmentDescriptionFlags(), swapChainData.colorFormat, vk::SampleCountFlagBits::e1, vk::AttachmentLoadOp::eLoad, vk::AttachmentStoreOp::eDontCare,
|
||||
vk::AttachmentLoadOp::eDontCare, vk::AttachmentStoreOp::eDontCare, vk::ImageLayout::eShaderReadOnlyOptimal, vk::ImageLayout::eShaderReadOnlyOptimal)
|
||||
};
|
||||
vk::AttachmentReference colorReference(0, vk::ImageLayout::eColorAttachmentOptimal);
|
||||
vk::AttachmentReference inputReference(1, vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||
vk::SubpassDescription subPass(vk::SubpassDescriptionFlags(), vk::PipelineBindPoint::eGraphics, 1, &inputReference, 1, &colorReference);
|
||||
vk::UniqueRenderPass renderPass = device->createRenderPassUnique(vk::RenderPassCreateInfo(vk::RenderPassCreateFlags(), 2, attachments, 1, &subPass));
|
||||
|
||||
glslang::InitializeProcess();
|
||||
vk::UniqueShaderModule vertexShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eVertex, vertexShaderText);
|
||||
vk::UniqueShaderModule fragmentShaderModule = vk::su::createShaderModule(device, vk::ShaderStageFlagBits::eFragment, fragmentShaderText);
|
||||
glslang::FinalizeProcess();
|
||||
|
||||
std::vector<vk::UniqueFramebuffer> framebuffers = vk::su::createFramebuffers(device, renderPass, swapChainData.imageViews, inputAttachmentView, surfaceData.extent);
|
||||
|
||||
vk::DescriptorPoolSize poolSize(vk::DescriptorType::eInputAttachment, 1);
|
||||
vk::UniqueDescriptorPool descriptorPool = device->createDescriptorPoolUnique(vk::DescriptorPoolCreateInfo(vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet, 1, 1, &poolSize));
|
||||
|
||||
std::vector<vk::UniqueDescriptorSet> descriptorSets = device->allocateDescriptorSetsUnique(vk::DescriptorSetAllocateInfo(descriptorPool.get(), 1, &descriptorSetLayout.get()));
|
||||
|
||||
vk::DescriptorImageInfo inputImageInfo(nullptr, inputAttachmentView.get(), vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||
vk::WriteDescriptorSet writeDescriptorSet(descriptorSets[0].get(), 0, 0, 1, vk::DescriptorType::eInputAttachment, &inputImageInfo);
|
||||
device->updateDescriptorSets(vk::ArrayProxy<const vk::WriteDescriptorSet>(1, &writeDescriptorSet), nullptr);
|
||||
|
||||
vk::UniquePipelineCache pipelineCache = device->createPipelineCacheUnique(vk::PipelineCacheCreateInfo());
|
||||
vk::UniquePipeline graphicsPipeline = vk::su::createGraphicsPipeline(device, pipelineCache, vertexShaderModule, fragmentShaderModule, 0, pipelineLayout, renderPass);
|
||||
|
||||
vk::UniqueSemaphore imageAcquiredSemaphore = device->createSemaphoreUnique(vk::SemaphoreCreateInfo());
|
||||
|
||||
vk::ResultValue<uint32_t> result = device->acquireNextImage2KHR(vk::AcquireNextImageInfoKHR(swapChainData.swapChain.get(), UINT64_MAX, imageAcquiredSemaphore.get()));
|
||||
assert(result.result == vk::Result::eSuccess);
|
||||
uint32_t currentBuffer = result.value;
|
||||
|
||||
vk::ClearValue clearValue;
|
||||
clearValue.color = vk::ClearColorValue(std::array<float, 4>({ 0.2f, 0.2f, 0.2f, 0.2f }));
|
||||
commandBuffers[0]->beginRenderPass(vk::RenderPassBeginInfo(renderPass.get(), framebuffers[currentBuffer].get(), vk::Rect2D(vk::Offset2D(0, 0), surfaceData.extent), 1, &clearValue), vk::SubpassContents::eInline);
|
||||
commandBuffers[0]->bindPipeline(vk::PipelineBindPoint::eGraphics, graphicsPipeline.get());
|
||||
commandBuffers[0]->bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout.get(), 0, descriptorSets[0].get(), nullptr);
|
||||
|
||||
vk::Viewport viewport(0.0f, 0.0f, static_cast<float>(surfaceData.extent.width), static_cast<float>(surfaceData.extent.height), 0.0f, 1.0f);
|
||||
commandBuffers[0]->setViewport(0, viewport);
|
||||
|
||||
vk::Rect2D scissor(vk::Offset2D(0, 0), surfaceData.extent);
|
||||
commandBuffers[0]->setScissor(0, scissor);
|
||||
|
||||
commandBuffers[0]->draw(3, 1, 0, 0);
|
||||
commandBuffers[0]->endRenderPass();
|
||||
commandBuffers[0]->end();
|
||||
|
||||
/* VULKAN_KEY_END */
|
||||
|
||||
vk::su::submitAndWait(device, graphicsQueue, commandBuffers[0]);
|
||||
|
||||
presentQueue.presentKHR(vk::PresentInfoKHR(0, nullptr, 1, &swapChainData.swapChain.get(), ¤tBuffer));
|
||||
Sleep(1000);
|
||||
|
||||
#if defined(VK_USE_PLATFORM_WIN32_KHR)
|
||||
DestroyWindow(surfaceData.window);
|
||||
#else
|
||||
#pragma error "unhandled platform"
|
||||
#endif
|
||||
}
|
||||
catch (vk::SystemError err)
|
||||
{
|
||||
std::cout << "vk::SystemError: " << err.what() << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
catch (std::runtime_error err)
|
||||
{
|
||||
std::cout << "std::runtime_error: " << err.what() << std::endl;
|
||||
exit(-1);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::cout << "unknown error\n";
|
||||
exit(-1);
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -19,6 +19,13 @@ struct VertexPC
|
||||
float r, g, b, a; // Color
|
||||
};
|
||||
|
||||
struct VertexPT
|
||||
{
|
||||
float x, y, z, w; // Position data
|
||||
float u, v; // texture u,v
|
||||
};
|
||||
|
||||
|
||||
static const VertexPC coloredCubeData[] =
|
||||
{
|
||||
// red face
|
||||
@ -65,3 +72,49 @@ static const VertexPC coloredCubeData[] =
|
||||
{ -1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f },
|
||||
};
|
||||
|
||||
static const VertexPT texturedCubeData[] =
|
||||
{
|
||||
// left face
|
||||
{ -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 0.0f },
|
||||
{ -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f },
|
||||
{ -1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f },
|
||||
{ -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f },
|
||||
{ -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 0.0f },
|
||||
{ -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f },
|
||||
// front face
|
||||
{ -1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f },
|
||||
{ 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 0.0f },
|
||||
{ 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f },
|
||||
{ -1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f },
|
||||
{ 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f },
|
||||
{ -1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f },
|
||||
// top face
|
||||
{ -1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 1.0f },
|
||||
{ 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f },
|
||||
{ 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f },
|
||||
{ -1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 1.0f },
|
||||
{ -1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f },
|
||||
{ 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 0.0f },
|
||||
// bottom face
|
||||
{ -1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f },
|
||||
{ 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f },
|
||||
{ -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f },
|
||||
{ -1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f },
|
||||
{ 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 0.0f },
|
||||
{ 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f },
|
||||
// right face
|
||||
{ 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f },
|
||||
{ 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f },
|
||||
{ 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f },
|
||||
{ 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f },
|
||||
{ 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f },
|
||||
{ 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f },
|
||||
// back face
|
||||
{ -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f },
|
||||
{ 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f },
|
||||
{ -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f },
|
||||
{ -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 0.0f },
|
||||
{ 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f },
|
||||
{ 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f },
|
||||
};
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "shaders.hpp"
|
||||
#include "vulkan/vulkan.hpp"
|
||||
#include "glslang/StandAlone/ResourceLimits.h"
|
||||
#include "SPIRV/GlslangToSpv.h"
|
||||
|
||||
namespace vk
|
||||
@ -38,102 +39,6 @@ namespace vk
|
||||
}
|
||||
}
|
||||
|
||||
void init(TBuiltInResource & resource)
|
||||
{
|
||||
resource.maxLights = 32;
|
||||
resource.maxClipPlanes = 6;
|
||||
resource.maxTextureUnits = 32;
|
||||
resource.maxTextureCoords = 32;
|
||||
resource.maxVertexAttribs = 64;
|
||||
resource.maxVertexUniformComponents = 4096;
|
||||
resource.maxVaryingFloats = 64;
|
||||
resource.maxVertexTextureImageUnits = 32;
|
||||
resource.maxCombinedTextureImageUnits = 80;
|
||||
resource.maxTextureImageUnits = 32;
|
||||
resource.maxFragmentUniformComponents = 4096;
|
||||
resource.maxDrawBuffers = 32;
|
||||
resource.maxVertexUniformVectors = 128;
|
||||
resource.maxVaryingVectors = 8;
|
||||
resource.maxFragmentUniformVectors = 16;
|
||||
resource.maxVertexOutputVectors = 16;
|
||||
resource.maxFragmentInputVectors = 15;
|
||||
resource.minProgramTexelOffset = -8;
|
||||
resource.maxProgramTexelOffset = 7;
|
||||
resource.maxClipDistances = 8;
|
||||
resource.maxComputeWorkGroupCountX = 65535;
|
||||
resource.maxComputeWorkGroupCountY = 65535;
|
||||
resource.maxComputeWorkGroupCountZ = 65535;
|
||||
resource.maxComputeWorkGroupSizeX = 1024;
|
||||
resource.maxComputeWorkGroupSizeY = 1024;
|
||||
resource.maxComputeWorkGroupSizeZ = 64;
|
||||
resource.maxComputeUniformComponents = 1024;
|
||||
resource.maxComputeTextureImageUnits = 16;
|
||||
resource.maxComputeImageUniforms = 8;
|
||||
resource.maxComputeAtomicCounters = 8;
|
||||
resource.maxComputeAtomicCounterBuffers = 1;
|
||||
resource.maxVaryingComponents = 60;
|
||||
resource.maxVertexOutputComponents = 64;
|
||||
resource.maxGeometryInputComponents = 64;
|
||||
resource.maxGeometryOutputComponents = 128;
|
||||
resource.maxFragmentInputComponents = 128;
|
||||
resource.maxImageUnits = 8;
|
||||
resource.maxCombinedImageUnitsAndFragmentOutputs = 8;
|
||||
resource.maxCombinedShaderOutputResources = 8;
|
||||
resource.maxImageSamples = 0;
|
||||
resource.maxVertexImageUniforms = 0;
|
||||
resource.maxTessControlImageUniforms = 0;
|
||||
resource.maxTessEvaluationImageUniforms = 0;
|
||||
resource.maxGeometryImageUniforms = 0;
|
||||
resource.maxFragmentImageUniforms = 8;
|
||||
resource.maxCombinedImageUniforms = 8;
|
||||
resource.maxGeometryTextureImageUnits = 16;
|
||||
resource.maxGeometryOutputVertices = 256;
|
||||
resource.maxGeometryTotalOutputComponents = 1024;
|
||||
resource.maxGeometryUniformComponents = 1024;
|
||||
resource.maxGeometryVaryingComponents = 64;
|
||||
resource.maxTessControlInputComponents = 128;
|
||||
resource.maxTessControlOutputComponents = 128;
|
||||
resource.maxTessControlTextureImageUnits = 16;
|
||||
resource.maxTessControlUniformComponents = 1024;
|
||||
resource.maxTessControlTotalOutputComponents = 4096;
|
||||
resource.maxTessEvaluationInputComponents = 128;
|
||||
resource.maxTessEvaluationOutputComponents = 128;
|
||||
resource.maxTessEvaluationTextureImageUnits = 16;
|
||||
resource.maxTessEvaluationUniformComponents = 1024;
|
||||
resource.maxTessPatchComponents = 120;
|
||||
resource.maxPatchVertices = 32;
|
||||
resource.maxTessGenLevel = 64;
|
||||
resource.maxViewports = 16;
|
||||
resource.maxVertexAtomicCounters = 0;
|
||||
resource.maxTessControlAtomicCounters = 0;
|
||||
resource.maxTessEvaluationAtomicCounters = 0;
|
||||
resource.maxGeometryAtomicCounters = 0;
|
||||
resource.maxFragmentAtomicCounters = 8;
|
||||
resource.maxCombinedAtomicCounters = 8;
|
||||
resource.maxAtomicCounterBindings = 1;
|
||||
resource.maxVertexAtomicCounterBuffers = 0;
|
||||
resource.maxTessControlAtomicCounterBuffers = 0;
|
||||
resource.maxTessEvaluationAtomicCounterBuffers = 0;
|
||||
resource.maxGeometryAtomicCounterBuffers = 0;
|
||||
resource.maxFragmentAtomicCounterBuffers = 1;
|
||||
resource.maxCombinedAtomicCounterBuffers = 1;
|
||||
resource.maxAtomicCounterBufferSize = 16384;
|
||||
resource.maxTransformFeedbackBuffers = 4;
|
||||
resource.maxTransformFeedbackInterleavedComponents = 64;
|
||||
resource.maxCullDistances = 8;
|
||||
resource.maxCombinedClipAndCullDistances = 8;
|
||||
resource.maxSamples = 4;
|
||||
resource.limits.nonInductiveForLoops = 1;
|
||||
resource.limits.whileLoops = 1;
|
||||
resource.limits.doWhileLoops = 1;
|
||||
resource.limits.generalUniformIndexing = 1;
|
||||
resource.limits.generalAttributeMatrixVectorIndexing = 1;
|
||||
resource.limits.generalVaryingIndexing = 1;
|
||||
resource.limits.generalSamplerIndexing = 1;
|
||||
resource.limits.generalVariableIndexing = 1;
|
||||
resource.limits.generalConstantMatrixVectorIndexing = 1;
|
||||
}
|
||||
|
||||
bool GLSLtoSPV(const vk::ShaderStageFlagBits shaderType, std::string const& glslShader, std::vector<unsigned int> &spvShader)
|
||||
{
|
||||
EShLanguage stage = translateShaderStage(shaderType);
|
||||
@ -144,13 +49,10 @@ namespace vk
|
||||
glslang::TShader shader(stage);
|
||||
shader.setStrings(shaderStrings, 1);
|
||||
|
||||
TBuiltInResource resource;
|
||||
init(resource);
|
||||
|
||||
// Enable SPIR-V and Vulkan rules when parsing GLSL
|
||||
EShMessages messages = (EShMessages)(EShMsgSpvRules | EShMsgVulkanRules);
|
||||
|
||||
if (!shader.parse(&resource, 100, false, messages))
|
||||
if (!shader.parse(&glslang::DefaultTBuiltInResource, 100, false, messages))
|
||||
{
|
||||
puts(shader.getInfoLog());
|
||||
puts(shader.getInfoDebugLog());
|
||||
|
@ -52,6 +52,31 @@ void main()
|
||||
}
|
||||
)";
|
||||
|
||||
// vertex shader with (P)osition and (T)exCoord in and (T)exCoord out
|
||||
const std::string vertexShaderText_PT_T = R"(
|
||||
#version 400
|
||||
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
#extension GL_ARB_shading_language_420pack : enable
|
||||
|
||||
layout (std140, binding = 0) uniform buffer
|
||||
{
|
||||
mat4 mvp;
|
||||
} uniformBuffer;
|
||||
|
||||
layout (location = 0) in vec4 pos;
|
||||
layout (location = 1) in vec2 inTexCoord;
|
||||
|
||||
layout (location = 0) out vec2 outTexCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
outTexCoord = inTexCoord;
|
||||
gl_Position = uniformBuffer.mvp * pos;
|
||||
}
|
||||
)";
|
||||
|
||||
|
||||
// fragment shader with (C)olor in and (C)olor out
|
||||
const std::string fragmentShaderText_C_C = R"(
|
||||
#version 400
|
||||
@ -69,3 +94,22 @@ void main()
|
||||
}
|
||||
)";
|
||||
|
||||
// fragment shader with (T)exCoord in and (C)olor out
|
||||
const std::string fragmentShaderText_T_C = R"(
|
||||
#version 400
|
||||
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
#extension GL_ARB_shading_language_420pack : enable
|
||||
|
||||
layout (binding = 1) uniform sampler2D tex;
|
||||
|
||||
layout (location = 0) in vec2 inTexCoord;
|
||||
|
||||
layout (location = 0) out vec4 outColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
outColor = texture(tex, inTexCoord);
|
||||
}
|
||||
)";
|
||||
|
||||
|
@ -130,13 +130,20 @@ namespace vk
|
||||
vk::PipelineShaderStageCreateInfo(vk::PipelineShaderStageCreateFlags(), vk::ShaderStageFlagBits::eFragment, fragmentShaderModule.get(), "main")
|
||||
};
|
||||
|
||||
vk::VertexInputBindingDescription vertexInputBindingDescription(0, vertexStride);
|
||||
vk::VertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
|
||||
vk::PipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo;
|
||||
if (0 < vertexStride)
|
||||
{
|
||||
vk::VertexInputAttributeDescription(0, 0, vk::Format::eR32G32B32A32Sfloat, 0),
|
||||
vk::VertexInputAttributeDescription(1, 0, vk::Format::eR32G32B32A32Sfloat, 16)
|
||||
};
|
||||
vk::PipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo(vk::PipelineVertexInputStateCreateFlags(), 1, &vertexInputBindingDescription, 2, vertexInputAttributeDescriptions);
|
||||
vk::VertexInputBindingDescription vertexInputBindingDescription(0, vertexStride);
|
||||
vk::VertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
|
||||
{
|
||||
vk::VertexInputAttributeDescription(0, 0, vk::Format::eR32G32B32A32Sfloat, 0),
|
||||
vk::VertexInputAttributeDescription(1, 0, vk::Format::eR32G32B32A32Sfloat, 16)
|
||||
};
|
||||
pipelineVertexInputStateCreateInfo.vertexBindingDescriptionCount = 1;
|
||||
pipelineVertexInputStateCreateInfo.pVertexBindingDescriptions = &vertexInputBindingDescription;
|
||||
pipelineVertexInputStateCreateInfo.vertexAttributeDescriptionCount = 2;
|
||||
pipelineVertexInputStateCreateInfo.pVertexAttributeDescriptions = vertexInputAttributeDescriptions;
|
||||
}
|
||||
|
||||
vk::PipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateCreateInfo(vk::PipelineInputAssemblyStateCreateFlags(), vk::PrimitiveTopology::eTriangleList);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user