2012-12-13 18:22:30 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
// Copyright 2013 Pixar
|
2012-12-13 18:22:30 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
// Licensed under the Apache License, Version 2.0 (the "Apache License")
|
|
|
|
// with the following modification; you may not use this file except in
|
|
|
|
// compliance with the Apache License and the following modification to it:
|
|
|
|
// Section 6. Trademarks. is deleted and replaced with:
|
2012-12-13 18:22:30 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
// 6. Trademarks. This License does not grant permission to use the trade
|
|
|
|
// names, trademarks, service marks, or product names of the Licensor
|
|
|
|
// and its affiliates, except as required to comply with Section 4(c) of
|
|
|
|
// the License and to reproduce the content of the NOTICE file.
|
2012-12-13 18:22:30 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
// You may obtain a copy of the Apache License at
|
2012-12-13 18:22:30 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
2013-07-18 21:19:50 +00:00
|
|
|
//
|
2013-09-26 19:04:57 +00:00
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the Apache License with the above modification is
|
|
|
|
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
|
|
// KIND, either express or implied. See the Apache License for the specific
|
|
|
|
// language governing permissions and limitations under the Apache License.
|
2012-12-13 18:22:30 +00:00
|
|
|
//
|
|
|
|
|
|
|
|
#include "../osd/d3d11ComputeController.h"
|
2014-12-04 04:04:35 +00:00
|
|
|
#include "../far/error.h"
|
2014-09-05 22:07:46 +00:00
|
|
|
#include "../osd/vertexDescriptor.h"
|
2012-12-13 18:22:30 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
#define INITGUID // for IID_ID3D11ShaderReflection
|
2012-12-13 18:22:30 +00:00
|
|
|
#include <D3D11.h>
|
2014-09-05 22:07:46 +00:00
|
|
|
#include <D3D11shader.h>
|
|
|
|
#include <D3Dcompiler.h>
|
2012-12-13 18:22:30 +00:00
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
#include <cassert>
|
2014-09-05 22:07:46 +00:00
|
|
|
#include <sstream>
|
2012-12-13 18:22:30 +00:00
|
|
|
|
|
|
|
namespace OpenSubdiv {
|
|
|
|
namespace OPENSUBDIV_VERSION {
|
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
namespace Osd {
|
|
|
|
|
2012-12-13 18:22:30 +00:00
|
|
|
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
|
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
static const char *shaderSource =
|
|
|
|
#include "../osd/hlslComputeKernel.gen.h"
|
|
|
|
;
|
2012-12-13 18:22:30 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
2012-12-13 18:22:30 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
// must match constant buffer declaration in hlslComputeKernel.hlsl
|
|
|
|
__declspec(align(16))
|
2012-12-13 18:22:30 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
struct KernelUniformArgs {
|
2012-12-13 18:22:30 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
int uniformStart, // batch
|
|
|
|
uniformEnd,
|
2012-12-13 18:22:30 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
uniformOffset, // primvar buffer descriptor
|
|
|
|
uniformNumCVs; // number of const control vertices padded at
|
|
|
|
};
|
2012-12-13 18:22:30 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
2012-12-13 18:22:30 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
class D3D11ComputeController::KernelBundle :
|
|
|
|
NonCopyable<D3D11ComputeController::KernelBundle> {
|
2014-05-06 15:53:36 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
public:
|
2014-05-06 15:53:36 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
KernelBundle() :
|
|
|
|
_computeShader(0),
|
|
|
|
_classLinkage(0),
|
|
|
|
_subStencilKernel(0),
|
|
|
|
_uniformArgs(0),
|
|
|
|
_workGroupSize(64) { }
|
2014-05-06 15:53:36 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
~KernelBundle() {
|
|
|
|
SAFE_RELEASE(_computeShader);
|
|
|
|
SAFE_RELEASE(_classLinkage);
|
|
|
|
SAFE_RELEASE(_subStencilKernel);
|
|
|
|
SAFE_RELEASE(_uniformArgs);
|
|
|
|
}
|
2013-03-08 01:50:15 +00:00
|
|
|
|
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
bool Compile(ID3D11DeviceContext *deviceContext,
|
|
|
|
VertexBufferDescriptor const &desc) {
|
|
|
|
|
|
|
|
_desc = VertexBufferDescriptor(0, desc.length, desc.stride);
|
|
|
|
|
|
|
|
DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;
|
|
|
|
#ifdef _DEBUG
|
|
|
|
dwShaderFlags |= D3DCOMPILE_DEBUG;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
std::ostringstream ss;
|
|
|
|
|
|
|
|
ss << _desc.offset; std::string offsetValue(ss.str()); ss.str("");
|
|
|
|
ss << _desc.length; std::string lengthValue(ss.str()); ss.str("");
|
|
|
|
ss << _desc.stride; std::string strideValue(ss.str()); ss.str("");
|
|
|
|
ss << _workGroupSize; std::string workgroupSizeValue(ss.str()); ss.str("");
|
|
|
|
|
|
|
|
D3D_SHADER_MACRO defines[] =
|
|
|
|
{ "OFFSET", offsetValue.c_str(),
|
|
|
|
"LENGTH", lengthValue.c_str(),
|
|
|
|
"STRIDE", strideValue.c_str(),
|
|
|
|
"WORK_GROUP_SIZE", workgroupSizeValue.c_str(),
|
|
|
|
0, 0 };
|
|
|
|
|
|
|
|
ID3DBlob * computeShaderBuffer = NULL;
|
|
|
|
ID3DBlob * errorBuffer = NULL;
|
|
|
|
|
|
|
|
HRESULT hr = D3DCompile(shaderSource, strlen(shaderSource),
|
|
|
|
NULL, &defines[0], NULL,
|
|
|
|
"cs_main", "cs_5_0",
|
|
|
|
dwShaderFlags, 0,
|
|
|
|
&computeShaderBuffer, &errorBuffer);
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
if (errorBuffer != NULL) {
|
2014-12-04 04:04:35 +00:00
|
|
|
Far::Error(Far::FAR_RUNTIME_ERROR,
|
2014-09-05 22:07:46 +00:00
|
|
|
"Error compiling HLSL shader: %s\n",
|
|
|
|
(CHAR*)errorBuffer->GetBufferPointer());
|
|
|
|
errorBuffer->Release();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2013-03-08 01:50:15 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
ID3D11Device *device = NULL;
|
|
|
|
deviceContext->GetDevice(&device);
|
|
|
|
assert(device);
|
2013-03-08 01:50:15 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
device->CreateClassLinkage(&_classLinkage);
|
|
|
|
assert(_classLinkage);
|
2013-03-08 01:50:15 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
device->CreateComputeShader(computeShaderBuffer->GetBufferPointer(),
|
|
|
|
computeShaderBuffer->GetBufferSize(),
|
|
|
|
_classLinkage,
|
|
|
|
&_computeShader);
|
|
|
|
assert(_computeShader);
|
2013-03-08 01:50:15 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
ID3D11ShaderReflection *reflector;
|
|
|
|
D3DReflect(computeShaderBuffer->GetBufferPointer(),
|
|
|
|
computeShaderBuffer->GetBufferSize(),
|
|
|
|
IID_ID3D11ShaderReflection, (void**) &reflector);
|
|
|
|
assert(reflector);
|
2013-03-08 01:50:15 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
assert(reflector->GetNumInterfaceSlots() == 1);
|
|
|
|
reflector->Release();
|
2013-03-08 01:50:15 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
computeShaderBuffer->Release();
|
2013-03-08 01:50:15 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
_classLinkage->GetClassInstance("computeStencil", 0, &_subStencilKernel);
|
|
|
|
assert(_subStencilKernel);
|
2013-03-08 01:50:15 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
return true;
|
|
|
|
}
|
2013-03-08 01:50:15 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
void ApplyStencilTableKernel(ID3D11DeviceContext *deviceContext,
|
|
|
|
Far::KernelBatch const &batch, int offset, int numCVs) {
|
2013-03-08 01:50:15 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
KernelUniformArgs args;
|
|
|
|
args.uniformStart = batch.start;
|
|
|
|
args.uniformEnd = batch.end;
|
|
|
|
args.uniformOffset = offset;
|
|
|
|
args.uniformNumCVs = numCVs;
|
2013-03-08 01:50:15 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
dispatchCompute(deviceContext, _subStencilKernel, args);
|
|
|
|
}
|
2014-05-30 06:02:19 +00:00
|
|
|
|
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
struct Match {
|
2013-03-08 01:50:15 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
Match(VertexBufferDescriptor const & d) : desc(d) { }
|
2014-05-30 06:02:19 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
bool operator() (KernelBundle const * kernel) {
|
|
|
|
return (desc.length==kernel->_desc.length and
|
|
|
|
desc.stride==kernel->_desc.stride);
|
|
|
|
}
|
2014-05-30 06:02:19 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
VertexBufferDescriptor desc;
|
|
|
|
};
|
2013-03-08 01:50:15 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
private:
|
2014-05-27 22:25:54 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
void dispatchCompute(ID3D11DeviceContext *deviceContext,
|
|
|
|
ID3D11ClassInstance * kernel, KernelUniformArgs const & args) {
|
2014-05-27 22:25:54 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
assert(deviceContext);
|
2014-05-27 22:25:54 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
int count = args.uniformEnd - args.uniformStart;
|
|
|
|
if (count <= 0) return;
|
2013-03-08 01:50:15 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
if (not _uniformArgs) {
|
|
|
|
ID3D11Device *device = NULL;
|
|
|
|
deviceContext->GetDevice(&device);
|
|
|
|
assert(device);
|
2013-03-08 01:50:15 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
D3D11_BUFFER_DESC cbDesc;
|
|
|
|
ZeroMemory(&cbDesc, sizeof(cbDesc));
|
|
|
|
cbDesc.Usage = D3D11_USAGE_DYNAMIC;
|
|
|
|
cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
|
|
|
|
cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
|
|
|
cbDesc.MiscFlags = 0;
|
|
|
|
cbDesc.ByteWidth = sizeof(KernelUniformArgs);
|
|
|
|
device->CreateBuffer(&cbDesc, NULL, &_uniformArgs);
|
|
|
|
}
|
|
|
|
assert(_uniformArgs);
|
2013-03-08 01:50:15 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
D3D11_MAPPED_SUBRESOURCE mappedResource;
|
|
|
|
deviceContext->Map(_uniformArgs, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
|
|
|
|
CopyMemory(mappedResource.pData, &args, sizeof(KernelUniformArgs));
|
2013-03-08 01:50:15 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
deviceContext->Unmap(_uniformArgs, 0);
|
|
|
|
deviceContext->CSSetConstantBuffers(0, 1, &_uniformArgs); // b0
|
2013-03-08 01:50:15 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
deviceContext->CSSetShader(_computeShader, &kernel, 1);
|
2015-01-13 09:59:06 +00:00
|
|
|
deviceContext->Dispatch((count + _workGroupSize - 1) / _workGroupSize, 1, 1);
|
2014-09-05 22:07:46 +00:00
|
|
|
}
|
2013-03-08 01:50:15 +00:00
|
|
|
|
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
private:
|
2013-03-08 01:50:15 +00:00
|
|
|
|
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
ID3D11ComputeShader * _computeShader;
|
2013-03-08 01:50:15 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
ID3D11ClassLinkage * _classLinkage;
|
2013-03-08 01:50:15 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
ID3D11ClassInstance * _subStencilKernel; // stencil compute kernel HLSL subroutine
|
2013-03-08 01:50:15 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
ID3D11Buffer * _uniformArgs; // uniform paramaeters for kernels
|
2014-06-10 23:31:44 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
VertexBufferDescriptor _desc; // primvar buffer descriptor
|
2014-06-10 23:31:44 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
int _workGroupSize;
|
|
|
|
};
|
2014-06-10 23:31:44 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
2014-06-10 23:31:44 +00:00
|
|
|
void
|
2014-09-05 22:07:46 +00:00
|
|
|
D3D11ComputeController::Synchronize() {
|
2014-06-10 23:31:44 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
if (not _query) {
|
|
|
|
ID3D11Device *device = NULL;
|
|
|
|
_deviceContext->GetDevice(&device);
|
|
|
|
assert(device);
|
2014-06-10 23:31:44 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
D3D11_QUERY_DESC desc;
|
|
|
|
desc.Query = D3D11_QUERY_EVENT;
|
|
|
|
desc.MiscFlags = 0;
|
|
|
|
device->CreateQuery(&desc, &_query);
|
|
|
|
}
|
|
|
|
_deviceContext->Flush();
|
|
|
|
_deviceContext->End(_query);
|
|
|
|
while (S_OK != _deviceContext->GetData(_query, NULL, 0, 0));
|
2014-06-10 23:31:44 +00:00
|
|
|
}
|
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
2014-06-10 23:31:44 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
D3D11ComputeController::KernelBundle const *
|
|
|
|
D3D11ComputeController::getKernel(VertexBufferDescriptor const &desc) {
|
2013-03-08 01:50:15 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
KernelRegistry::iterator it =
|
|
|
|
std::find_if(_kernelRegistry.begin(), _kernelRegistry.end(),
|
|
|
|
KernelBundle::Match(desc));
|
2013-03-08 01:50:15 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
if (it != _kernelRegistry.end()) {
|
|
|
|
return *it;
|
|
|
|
} else {
|
|
|
|
assert(_deviceContext);
|
|
|
|
KernelBundle * kernelBundle = new KernelBundle();
|
|
|
|
kernelBundle->Compile(_deviceContext, desc);
|
|
|
|
_kernelRegistry.push_back(kernelBundle);
|
|
|
|
return kernelBundle;
|
|
|
|
}
|
2013-03-08 01:50:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-09-05 22:07:46 +00:00
|
|
|
D3D11ComputeController::bindBuffer() {
|
2013-03-08 01:50:15 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
// Unbind the vertexBuffer from the input assembler
|
|
|
|
ID3D11Buffer *NULLBuffer = 0;
|
|
|
|
UINT voffset = 0, vstride = 0;
|
|
|
|
_deviceContext->IASetVertexBuffers(0, 1, &NULLBuffer, &voffset, &vstride);
|
2013-03-08 01:50:15 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
// Unbind the vertexBuffer from the vertex shader
|
|
|
|
ID3D11ShaderResourceView *NULLSRV = 0;
|
|
|
|
_deviceContext->VSSetShaderResources(0, 1, &NULLSRV);
|
|
|
|
|
|
|
|
if (_currentBindState.buffer)
|
|
|
|
_deviceContext->CSSetUnorderedAccessViews(0, 1, &_currentBindState.buffer, 0); // u0
|
2013-03-08 01:50:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-09-05 22:07:46 +00:00
|
|
|
D3D11ComputeController::unbindBuffer() {
|
|
|
|
assert(_deviceContext);
|
|
|
|
ID3D11UnorderedAccessView *UAViews[] = { 0 };
|
|
|
|
_deviceContext->CSSetUnorderedAccessViews(0, 1, UAViews, 0); // u0
|
2013-03-08 01:50:15 +00:00
|
|
|
}
|
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
2013-03-08 01:50:15 +00:00
|
|
|
void
|
2014-09-05 22:07:46 +00:00
|
|
|
D3D11ComputeController::ApplyStencilTableKernel(
|
|
|
|
Far::KernelBatch const &batch, D3D11ComputeContext const *context) const {
|
2013-03-08 01:50:15 +00:00
|
|
|
|
|
|
|
assert(context);
|
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
// XXXX manuelk messy const drop forced by D3D API - could use better solution
|
|
|
|
D3D11ComputeController::KernelBundle * bundle =
|
|
|
|
const_cast<D3D11ComputeController::KernelBundle *>(_currentBindState.kernelBundle);
|
2013-03-08 01:50:15 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
bundle->ApplyStencilTableKernel(_deviceContext,
|
|
|
|
batch, _currentBindState.desc.offset, context->GetNumControlVertices());
|
|
|
|
}
|
2013-03-08 01:50:15 +00:00
|
|
|
|
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
2013-03-08 01:50:15 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
D3D11ComputeController::D3D11ComputeController(
|
|
|
|
ID3D11DeviceContext *deviceContext)
|
|
|
|
: _deviceContext(deviceContext), _query(0) {
|
|
|
|
}
|
2013-03-08 01:50:15 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
D3D11ComputeController::~D3D11ComputeController() {
|
2014-05-06 15:53:36 +00:00
|
|
|
|
2014-09-05 22:07:46 +00:00
|
|
|
for (KernelRegistry::iterator it = _kernelRegistry.begin();
|
|
|
|
it != _kernelRegistry.end(); ++it) {
|
|
|
|
delete *it;
|
2013-03-08 01:50:15 +00:00
|
|
|
}
|
2014-09-05 22:07:46 +00:00
|
|
|
SAFE_RELEASE(_query);
|
2013-03-08 01:50:15 +00:00
|
|
|
}
|
2014-09-05 22:07:46 +00:00
|
|
|
|
|
|
|
} // end namespace Osd
|
|
|
|
|
2012-12-13 18:22:30 +00:00
|
|
|
} // end namespace OPENSUBDIV_VERSION
|
|
|
|
} // end namespace OpenSubdiv
|