void TriangleVK::OnCreate(DeviceVK* pDevice, DynamicBufferRingVK *pConstantBufferRing, StaticBufferPoolVK *pStaticGeom, VkRenderPass renderPass)
{
    m_pDevice = pDevice;
    m_pConstantBufferRing = pConstantBufferRing;

    VkResult res;

    struct Vertex {
        float posX, posY, posZ, posW;  // Position data
        float r, g, b, a;              // Color
    };
#define XYZ1(_x_, _y_, _z_) (_x_), (_y_), (_z_), 1.f

    const Vertex g_vb_solid_face_colors_Data[] = {
        // red face
        { XYZ1(-1, -1, 1), XYZ1(1.f, 0.f, 0.f) },
        { XYZ1(-1, 1, 1), XYZ1(1.f, 0.f, 0.f) },
        { XYZ1(1, -1, 1), XYZ1(1.f, 0.f, 0.f) },
        { XYZ1(1, -1, 1), XYZ1(1.f, 0.f, 0.f) },
        { XYZ1(-1, 1, 1), XYZ1(1.f, 0.f, 0.f) },
        { XYZ1(1, 1, 1), XYZ1(1.f, 0.f, 0.f) },
        // green face
        { XYZ1(-1, -1, -1), XYZ1(0.f, 1.f, 0.f) },
        { XYZ1(1, -1, -1), XYZ1(0.f, 1.f, 0.f) },
        { XYZ1(-1, 1, -1), XYZ1(0.f, 1.f, 0.f) },
        { XYZ1(-1, 1, -1), XYZ1(0.f, 1.f, 0.f) },
        { XYZ1(1, -1, -1), XYZ1(0.f, 1.f, 0.f) },
        { XYZ1(1, 1, -1), XYZ1(0.f, 1.f, 0.f) },
        // blue face
        { XYZ1(-1, 1, 1), XYZ1(0.f, 0.f, 1.f) },
        { XYZ1(-1, -1, 1), XYZ1(0.f, 0.f, 1.f) },
        { XYZ1(-1, 1, -1), XYZ1(0.f, 0.f, 1.f) },
        { XYZ1(-1, 1, -1), XYZ1(0.f, 0.f, 1.f) },
        { XYZ1(-1, -1, 1), XYZ1(0.f, 0.f, 1.f) },
        { XYZ1(-1, -1, -1), XYZ1(0.f, 0.f, 1.f) },
        // yellow face
        { XYZ1(1, 1, 1), XYZ1(1.f, 1.f, 0.f) },
        { XYZ1(1, 1, -1), XYZ1(1.f, 1.f, 0.f) },
        { XYZ1(1, -1, 1), XYZ1(1.f, 1.f, 0.f) },
        { XYZ1(1, -1, 1), XYZ1(1.f, 1.f, 0.f) },
        { XYZ1(1, 1, -1), XYZ1(1.f, 1.f, 0.f) },
        { XYZ1(1, -1, -1), XYZ1(1.f, 1.f, 0.f) },
        // magenta face
        { XYZ1(1, 1, 1), XYZ1(1.f, 0.f, 1.f) },
        { XYZ1(-1, 1, 1), XYZ1(1.f, 0.f, 1.f) },
        { XYZ1(1, 1, -1), XYZ1(1.f, 0.f, 1.f) },
        { XYZ1(1, 1, -1), XYZ1(1.f, 0.f, 1.f) },
        { XYZ1(-1, 1, 1), XYZ1(1.f, 0.f, 1.f) },
        { XYZ1(-1, 1, -1), XYZ1(1.f, 0.f, 1.f) },
        // cyan face
        { XYZ1(1, -1, 1), XYZ1(0.f, 1.f, 1.f) },
        { XYZ1(1, -1, -1), XYZ1(0.f, 1.f, 1.f) },
        { XYZ1(-1, -1, 1), XYZ1(0.f, 1.f, 1.f) },
        { XYZ1(-1, -1, 1), XYZ1(0.f, 1.f, 1.f) },
        { XYZ1(1, -1, -1), XYZ1(0.f, 1.f, 1.f) },
        { XYZ1(-1, -1, -1), XYZ1(0.f, 1.f, 1.f) },
    };

    int vertices = 6 * 6;
    int vertexSize = 8 * sizeof(float);

    void *pData;
    pStaticGeom->AllocVertexBuffer(vertices, vertexSize, &pData, &m_geometry);
    memcpy(pData, g_vb_solid_face_colors_Data, sizeof(g_vb_solid_face_colors_Data));

    ///////////////////////////////////////////////
    // shaders
    const char *vertShaderText =
        "#version 400\n"
        "#extension GL_ARB_separate_shader_objects : enable\n"
        "#extension GL_ARB_shading_language_420pack : enable\n"
        "layout (std140, binding = 0) uniform bufferVals {\n"
        "    mat4 mvp;\n"
        "} myBufferVals;\n"
        "layout (location = 0) in vec4 pos;\n"
        "layout (location = 1) in vec4 inColor;\n"
        "layout (location = 0) out vec4 outColor;\n"
        "void main() {\n"
        "   outColor = inColor;\n"
        "   gl_Position = myBufferVals.mvp * pos;\n"
        "}\n";

    const char *fragShaderText =
        "#version 400\n"
        "#extension GL_ARB_separate_shader_objects : enable\n"
        "#extension GL_ARB_shading_language_420pack : enable\n"
        "layout (location = 0) in vec4 color;\n"
        "layout (location = 0) out vec4 outColor;\n"
        "void main() {\n"
        "   outColor = color;\n"
        "}\n";

    /////////////////////////////////////////////
    // Compile and create shaders
    
    init_glslang();
    
    std::map<std::string, std::string> attributeDefines;

    VkPipelineShaderStageCreateInfo m_vertexShader;
    res = VKCompile(pDevice->GetDevice(), SST_GLSL, VK_SHADER_STAGE_VERTEX_BIT, vertShaderText, "main", attributeDefines, &m_vertexShader);
    assert(res == VK_SUCCESS);

    VkPipelineShaderStageCreateInfo m_fragmentShader;
    res = VKCompile(pDevice->GetDevice(), SST_GLSL, VK_SHADER_STAGE_FRAGMENT_BIT, fragShaderText, "main", attributeDefines, &m_fragmentShader);
    assert(res == VK_SUCCESS);

    finalize_glslang();
    
    std::vector<VkPipelineShaderStageCreateInfo> shaderStages = { m_vertexShader, m_fragmentShader };

    /////////////////////////////////////////////
    // Create descriptor pool

    std::vector<VkDescriptorPoolSize> type_count = { { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1} };

    VkDescriptorPoolCreateInfo descriptor_pool = {};
    descriptor_pool.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
    descriptor_pool.pNext = NULL;
    descriptor_pool.maxSets = 1;
    descriptor_pool.poolSizeCount = (uint32_t)type_count.size();
    descriptor_pool.pPoolSizes = type_count.data();

    res = vkCreateDescriptorPool(pDevice->GetDevice(), &descriptor_pool, NULL, &m_descriptorPool);
    assert(res == VK_SUCCESS);

    /////////////////////////////////////////////
    // Create pipeline layout

    VkDescriptorSetLayoutBinding layout_bindings[1];
    layout_bindings[0].binding = 0;
    layout_bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
    layout_bindings[0].descriptorCount = 1;
    layout_bindings[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
    layout_bindings[0].pImmutableSamplers = NULL;

    /* Next take layout bindings and use them to create a descriptor set layout
    */
    VkDescriptorSetLayoutCreateInfo descriptor_layout = {};
    descriptor_layout.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
    descriptor_layout.pNext = NULL;
    descriptor_layout.flags = 0;
    descriptor_layout.bindingCount = 1;
    descriptor_layout.pBindings = layout_bindings;

    std::vector<VkDescriptorSetLayout> desc_layout;
    desc_layout.resize(1);
    res = vkCreateDescriptorSetLayout(pDevice->GetDevice(), &descriptor_layout, NULL, desc_layout.data());
    assert(res == VK_SUCCESS);

    /* Now use the descriptor layout to create a pipeline layout */
    VkPipelineLayoutCreateInfo pPipelineLayoutCreateInfo = {};
    pPipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
    pPipelineLayoutCreateInfo.pNext = NULL;
    pPipelineLayoutCreateInfo.pushConstantRangeCount = 0;
    pPipelineLayoutCreateInfo.pPushConstantRanges = NULL;
    pPipelineLayoutCreateInfo.setLayoutCount = (uint32_t)desc_layout.size();
    pPipelineLayoutCreateInfo.pSetLayouts = desc_layout.data();

    res = vkCreatePipelineLayout(pDevice->GetDevice(), &pPipelineLayoutCreateInfo, NULL, &m_pipelineLayout);
    assert(res == VK_SUCCESS);

    /////////////////////////////////////////////
    // Create descriptor sets
    VkDescriptorSetAllocateInfo alloc_info[1];
    alloc_info[0].sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
    alloc_info[0].pNext = NULL;
    alloc_info[0].descriptorPool = m_descriptorPool;
    alloc_info[0].descriptorSetCount = (uint32_t)desc_layout.size();
    alloc_info[0].pSetLayouts = desc_layout.data();


    m_descriptorSets.resize(desc_layout.size());
    res = vkAllocateDescriptorSets(pDevice->GetDevice(), alloc_info, m_descriptorSets.data());
    assert(res == VK_SUCCESS);

    /////////////////////////////////////////////
    // Create pipeline

    // vertex input state

    VkVertexInputBindingDescription vi_binding = {};
    vi_binding.binding = 0;
    vi_binding.stride = sizeof(float) * 8;
    vi_binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;

    std::vector<VkVertexInputAttributeDescription> vi_attrs(2);
    // Position
    vi_attrs[0].location = 0;
    vi_attrs[0].binding = 0;
    vi_attrs[0].format = VK_FORMAT_R32G32B32A32_SFLOAT;
    vi_attrs[0].offset = 0;
    // Normal
    vi_attrs[1].location = 1;
    vi_attrs[1].binding = 0;
    vi_attrs[1].format = VK_FORMAT_R32G32B32A32_SFLOAT;
    vi_attrs[1].offset = sizeof(float) * 4;

    VkPipelineVertexInputStateCreateInfo vi = {};
    vi.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
    vi.pNext = NULL;
    vi.flags = 0;
    vi.vertexBindingDescriptionCount = 1;
    vi.pVertexBindingDescriptions = &vi_binding;
    vi.vertexAttributeDescriptionCount = (uint32_t)vi_attrs.size();
    vi.pVertexAttributeDescriptions = vi_attrs.data();

    // input assembly state

    VkPipelineInputAssemblyStateCreateInfo ia;
    ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
    ia.pNext = NULL;
    ia.flags = 0;
    ia.primitiveRestartEnable = VK_FALSE;
    ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;

    // rasterizer state

    VkPipelineRasterizationStateCreateInfo rs;
    rs.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
    rs.pNext = NULL;
    rs.flags = 0;
    rs.polygonMode = VK_POLYGON_MODE_FILL;
    rs.cullMode = VK_CULL_MODE_BACK_BIT;
    rs.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
    rs.depthClampEnable = VK_FALSE;
    rs.rasterizerDiscardEnable = VK_FALSE;
    rs.depthBiasEnable = VK_FALSE;
    rs.depthBiasConstantFactor = 0;
    rs.depthBiasClamp = 0;
    rs.depthBiasSlopeFactor = 0;
    rs.lineWidth = 1.0f;

    VkPipelineColorBlendAttachmentState att_state[1];
    att_state[0].colorWriteMask = 0xf;
    att_state[0].blendEnable = VK_FALSE;
    att_state[0].alphaBlendOp = VK_BLEND_OP_ADD;
    att_state[0].colorBlendOp = VK_BLEND_OP_ADD;
    att_state[0].srcColorBlendFactor = VK_BLEND_FACTOR_ZERO;
    att_state[0].dstColorBlendFactor = VK_BLEND_FACTOR_ZERO;
    att_state[0].srcAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
    att_state[0].dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;

    // Color blend state

    VkPipelineColorBlendStateCreateInfo cb;
    cb.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
    cb.flags = 0;
    cb.pNext = NULL;
    cb.attachmentCount = 1;
    cb.pAttachments = att_state;
    cb.logicOpEnable = VK_FALSE;
    cb.logicOp = VK_LOGIC_OP_NO_OP;
    cb.blendConstants[0] = 1.0f;
    cb.blendConstants[1] = 1.0f;
    cb.blendConstants[2] = 1.0f;
    cb.blendConstants[3] = 1.0f;

    std::vector<VkDynamicState> dynamicStateEnables = {
        VK_DYNAMIC_STATE_VIEWPORT,
        VK_DYNAMIC_STATE_SCISSOR 
    };
    VkPipelineDynamicStateCreateInfo dynamicState = {};
    dynamicState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
    dynamicState.pNext = NULL;
    dynamicState.pDynamicStates = dynamicStateEnables.data();
    dynamicState.dynamicStateCount = (uint32_t)dynamicStateEnables.size();

    // view port state

    VkPipelineViewportStateCreateInfo vp = {};
    vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
    vp.pNext = NULL;
    vp.flags = 0;
    vp.viewportCount = 1;
    vp.scissorCount = 1;
    vp.pScissors = NULL;
    vp.pViewports = NULL;

    // depth stencil state

    VkPipelineDepthStencilStateCreateInfo ds;
    ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
    ds.pNext = NULL;
    ds.flags = 0;
    ds.depthTestEnable = true;
    ds.depthWriteEnable = true;
    ds.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
    ds.depthBoundsTestEnable = VK_FALSE;
    ds.stencilTestEnable = VK_FALSE;
    ds.back.failOp = VK_STENCIL_OP_KEEP;
    ds.back.passOp = VK_STENCIL_OP_KEEP;
    ds.back.compareOp = VK_COMPARE_OP_ALWAYS;
    ds.back.compareMask = 0;
    ds.back.reference = 0;
    ds.back.depthFailOp = VK_STENCIL_OP_KEEP;
    ds.back.writeMask = 0;
    ds.minDepthBounds = 0;
    ds.maxDepthBounds = 0;
    ds.stencilTestEnable = VK_FALSE;
    ds.front = ds.back;

    // multi sample state

    VkPipelineMultisampleStateCreateInfo ms;
    ms.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
    ms.pNext = NULL;
    ms.flags = 0;
    ms.pSampleMask = NULL;
    ms.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
    ms.sampleShadingEnable = VK_FALSE;
    ms.alphaToCoverageEnable = VK_FALSE;
    ms.alphaToOneEnable = VK_FALSE;
    ms.minSampleShading = 0.0;

    // create pipeline cache

    VkPipelineCacheCreateInfo pipelineCache;
    pipelineCache.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
    pipelineCache.pNext = NULL;
    pipelineCache.initialDataSize = 0;
    pipelineCache.pInitialData = NULL;
    pipelineCache.flags = 0;
    res = vkCreatePipelineCache(pDevice->GetDevice(), &pipelineCache, NULL, &m_pipelineCache);
    assert(res == VK_SUCCESS);

    // create pipeline 

    VkGraphicsPipelineCreateInfo pipeline = {};
    pipeline.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
    pipeline.pNext = NULL;
    pipeline.layout = m_pipelineLayout;
    pipeline.basePipelineHandle = VK_NULL_HANDLE;
    pipeline.basePipelineIndex = 0;
    pipeline.flags = 0;
    pipeline.pVertexInputState = &vi;
    pipeline.pInputAssemblyState = &ia;
    pipeline.pRasterizationState = &rs;
    pipeline.pColorBlendState = &cb;
    pipeline.pTessellationState = NULL;
    pipeline.pMultisampleState = &ms;
    pipeline.pDynamicState = &dynamicState;
    pipeline.pViewportState = &vp;
    pipeline.pDepthStencilState = &ds;
    pipeline.pStages = shaderStages.data();
    pipeline.stageCount = (uint32_t)shaderStages.size();
    pipeline.renderPass = renderPass;
    pipeline.subpass = 0;

    res = vkCreateGraphicsPipelines(pDevice->GetDevice(), m_pipelineCache, 1, &pipeline, NULL, &m_pipeline);
    assert(res == VK_SUCCESS);
}
 * be used as a texture again. Use the second set of vertices to draw a quad to
 * the right of the first. Do this all in one command buffer.  The image should
 * be a LunarG logo quad on the left and a green quad on the right.
 */

#include <util_init.hpp>
#include <assert.h>
#include <string.h>
#include <cstdlib>
#include <cube_data.h>

// Using OpenGL based glm, so Y is upside down between OpenGL and Vulkan

static const VertexUV vb_Data[] = {
    // Textured quad:
    {XYZ1(-2, -0.5, -1), UV(0.f, 0.f)},  // lft-top        / Z
    {XYZ1(-1, -0.5, -1), UV(1.f, 0.f)},  // rgt-top       /
    {XYZ1(-2, 0.5, -1), UV(0.f, 1.f)},   // lft-btm      +------> X
    {XYZ1(-2, 0.5, -1), UV(0.f, 1.f)},   // lft-btm      |
    {XYZ1(-1, -0.5, -1), UV(1.f, 0.f)},  // rgt-top      |
    {XYZ1(-1, 0.5, -1), UV(1.f, 1.f)},   // rgt-btm      v Y
    // Green quad:
    {XYZ1(1, -0.5, -1), UV(0.f, 0.f)},  // lft-top
    {XYZ1(2, -0.5, -1), UV(1.f, 0.f)},  // rgt-top
    {XYZ1(1, 0.5, -1), UV(0.f, 1.f)},   // lft-btm
    {XYZ1(1, 0.5, -1), UV(0.f, 1.f)},   // lft-btm
    {XYZ1(2, -0.5, -1), UV(1.f, 0.f)},  // rgt-top
    {XYZ1(2, 0.5, -1), UV(1.f, 1.f)},   // rgt-btm
};

#define DEPTH_PRESENT false
/* Set up Vulkan pipeline and use three threads to create 3       */
/* command buffers, each using a vertex buffer to draw a triangle */

#include <util_init.hpp>
#include <assert.h>
#include <string.h>
#include <cstdlib>
#include <samples_platform.h>

struct Vertex {
    float posX, posY, posZ, posW; // Position data
    float r, g, b, a;             // Color
};
#define XYZ1(_x_, _y_, _z_) (_x_), (_y_), (_z_), 1.f
static const Vertex triData[] = {
    {XYZ1(-0.25, -0.25, 0), XYZ1(1.f, 0.f, 0.f)},
    {XYZ1(0.25, -0.25, 0), XYZ1(1.f, 0.f, 0.f)},
    {XYZ1(0, 0.25, 0), XYZ1(1.f, 0.f, 0.f)},
    {XYZ1(-0.75, -0.25, 0), XYZ1(0.f, 1.f, 0.f)},
    {XYZ1(-0.25, -0.25, 0), XYZ1(0.f, 1.f, 0.f)},
    {XYZ1(-0.5, 0.25, 0), XYZ1(0.f, 1.f, 0.f)},
    {XYZ1(0.25, -0.25, 0), XYZ1(0.f, 0.f, 1.f)},
    {XYZ1(0.75, -0.25, 0), XYZ1(0.f, 0.f, 1.f)},
    {XYZ1(0.5, 0.25, 0), XYZ1(0.f, 0.f, 1.f)},
};

struct {
    VkBuffer buf;
    VkDeviceMemory mem;
} vertex_buffer[3];
Exemple #4
0
ASMmxBase::VolumeVec ASMmxBase::establishBases(Go::SplineVolume* svol,
                                               MixedType type)
{
  VolumeVec result(2);
  // With mixed methods we need two separate spline spaces
  if (type == FULL_CONT_RAISE_BASIS1 || type == FULL_CONT_RAISE_BASIS2)
  {
    // basis1 should be one degree higher than basis2 and C^p-1 continuous
    int ndim = svol->dimension();
    Go::BsplineBasis b1 = svol->basis(0).extendedBasis(svol->order(0)+1);
    Go::BsplineBasis b2 = svol->basis(1).extendedBasis(svol->order(1)+1);
    Go::BsplineBasis b3 = svol->basis(2).extendedBasis(svol->order(2)+1);
    /* To lower order and regularity this can be used instead
    std::vector<double>::const_iterator first = ++surf->basis(0).begin();
    std::vector<double>::const_iterator last  = --surf->basis(0).end();
    Go::BsplineBasis b1 = Go::BsplineBasis(surf->order_u()-1,first,last);
    first =  ++surf->basis(1).begin();
    last  =  --surf->basis(1).end();
    Go::BsplineBasis b2 = Go::BsplineBasis(surf->order_v()-1,first,last);
    */

    // Compute parameter values of the Greville points
    size_t i;
    RealArray ug(b1.numCoefs()), vg(b2.numCoefs()), wg(b3.numCoefs());
    for (i = 0; i < ug.size(); i++)
      ug[i] = b1.grevilleParameter(i);
    for (i = 0; i < vg.size(); i++)
      vg[i] = b2.grevilleParameter(i);
    for (i = 0; i < wg.size(); i++)
      wg[i] = b3.grevilleParameter(i);

    if (svol->rational()) {
      std::vector<double> rCoefs(svol->rcoefs_begin(), svol->rcoefs_end());

      // we normally would set coefs as (x*w, y*w, w)
      // however, gotools use this representation internally already.

      // instance a Bspline surface in ndim+1
      Go::SplineVolume vol2(svol->basis(0), svol->basis(1), svol->basis(2), rCoefs.begin(), ndim+1, false);

      // interpolate the Bspline surface onto new basis
      RealArray XYZ((ndim+1)*ug.size()*vg.size()*wg.size());
      vol2.gridEvaluator(XYZ,ug,vg,wg);
      std::unique_ptr<Go::SplineVolume> svol3(Go::VolumeInterpolator::regularInterpolation(b1,b2,b3,ug,vg,wg,XYZ,ndim+1,false,XYZ));

      // new rational coefs are (x/w', y/w', w')
      // apparently gotools will rescale coeffs on surface creation.
      result[0].reset(new Go::SplineVolume(svol3->basis(0), svol3->basis(1), svol3->basis(2), svol3->coefs_begin(), ndim, true));
    } else {
      RealArray XYZ(ndim*ug.size()*vg.size()*wg.size());
      // Evaluate the spline surface at all points
      svol->gridEvaluator(ug,vg,wg,XYZ);
      // Project the coordinates onto the new basis (the 2nd XYZ is dummy here)
      result[0].reset(Go::VolumeInterpolator::regularInterpolation(b1,b2,b3,
                                                                   ug,vg,wg,XYZ,ndim,
                                                                   false,XYZ));
    }
    result[1].reset(new Go::SplineVolume(*svol));
  }
  else if (type == REDUCED_CONT_RAISE_BASIS1 || type == REDUCED_CONT_RAISE_BASIS2)
  {
    // Order-elevate basis1 such that it is of one degree higher than basis2
    // but only C^p-2 continuous
    result[0].reset(new Go::SplineVolume(*svol));
    result[0]->raiseOrder(1,1,1);
    result[1].reset(new Go::SplineVolume(*svol));
  }
  else if (ASMmxBase::Type == ASMmxBase::DIV_COMPATIBLE)
  {
    result.resize(4);

    // basis1 should be one degree higher than basis2 and C^p-1 continuous
    int ndim = svol->dimension();
    Go::BsplineBasis a1 = svol->basis(0);
    Go::BsplineBasis a2 = svol->basis(1);
    Go::BsplineBasis a3 = svol->basis(2);
    Go::BsplineBasis b1 = svol->basis(0).extendedBasis(svol->order(0)+1);
    Go::BsplineBasis b2 = svol->basis(1).extendedBasis(svol->order(1)+1);
    Go::BsplineBasis b3 = svol->basis(2).extendedBasis(svol->order(2)+1);

    // Compute parameter values of the Greville points
    size_t i;
    RealArray u0(a1.numCoefs()), v0(a2.numCoefs()), w0(a3.numCoefs());
    for (i = 0; i < u0.size(); i++)
      u0[i] = a1.grevilleParameter(i);
    for (i = 0; i < v0.size(); i++)
      v0[i] = a2.grevilleParameter(i);
    for (i = 0; i < w0.size(); i++)
      w0[i] = a3.grevilleParameter(i);
    RealArray ug(b1.numCoefs()), vg(b2.numCoefs()), wg(b3.numCoefs());
    for (i = 0; i < ug.size(); i++)
      ug[i] = b1.grevilleParameter(i);
    for (i = 0; i < vg.size(); i++)
      vg[i] = b2.grevilleParameter(i);
    for (i = 0; i < wg.size(); i++)
      wg[i] = b3.grevilleParameter(i);

    // Evaluate the spline surface at all points
    // Project the coordinates onto the new basis (the 2nd XYZ is dummy here)
    RealArray XYZ0(ndim*ug.size()*v0.size()*w0.size()), XYZ1(ndim*u0.size()*vg.size()*w0.size()), XYZ2(ndim*u0.size()*v0.size()*wg.size());
    svol->gridEvaluator(ug,v0,w0,XYZ0);
    svol->gridEvaluator(u0,vg,w0,XYZ1);
    svol->gridEvaluator(u0,v0,wg,XYZ2);
    result[0].reset(Go::VolumeInterpolator::regularInterpolation(b1,a2,a3,
                                                                 ug,v0,w0,XYZ0,ndim,
                                                                 false,XYZ0));
    result[1].reset(Go::VolumeInterpolator::regularInterpolation(a1,b2,a3,
                                                                 u0,vg,w0,XYZ1,ndim,
                                                                 false,XYZ1));
    result[2].reset(Go::VolumeInterpolator::regularInterpolation(a1,a2,b3,
                                                                 u0,v0,wg,XYZ2,ndim,
                                                                 false,XYZ2));
    result[3].reset(new Go::SplineVolume(*svol));
    geoBasis = 4;
  }

  if (type == FULL_CONT_RAISE_BASIS2 || type == REDUCED_CONT_RAISE_BASIS2)
    std::swap(result[0], result[1]);

  return result;
}